I want to receive a screenshot on server inside a thread and tried to use code that was suggested in this answer of a experient member (Delphi programmer) that second he, this code only works in ThreadBlocking
mode.
I already put TServerSocket
(Delphi component) in this mode, but when the component is in this mode, any connection cannot be received on server from a client Android made in Java (that also use Socket
to establish this connection).
Now I want to know (mainly of a Android programmer) if on client side (Android) Socket
also must be in ThreadBlocking
to establish this connection with success, or what's missing to all this work fine like it should?
Here are the two part of my code:
Java (Android):
private Socket clientSocket;
private final int SERVERPORT = 60;
private final String SERVER_IP = "192.168.15.13";
/////////////////////////////////////////////// CLIENTSOCKET //////////////////////////////////////////////////////
class ClientThread implements Runnable {
@Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
clientSocket = new Socket(serverAddr, SERVERPORT);
new Thread(new CommsThread()).start();
} catch (Exception e1) {
System.out.println(e1.toString());
}
}
}
class CommsThread implements Runnable {
@Override
public void run() {
try {
System.out.println("Waiting for server request");
while(clientSocket.isConnected()){
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())),true);
if (reader.ready()) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
if(line != null && !line.trim().isEmpty()) {
if(line.equalsIgnoreCase("screencapture")){
// Take screenshot with MediaProjection api
// Send to server =>
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
byte[] array = bos.toByteArray();
DataOutputStream dos = new DataOutputStream(clientSocket.getOutputStream());
dos.writeInt(array.length);
dos.write(array, 0, array.length);
dos.flush();
}
if(line.equalsIgnoreCase("exit"))
// Do something
break;
}
}
}
}
System.out.println("Shutting down Socket!!");
clientSocket.close();
} catch (Exception e1) {
System.out.println(e1.toString());
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new ClientThread()).start();
}
Delphi (Object Pascal):
uses
ScktComp, Winsock, pngimage;
type
TSock_Thread = class(TServerClientThread)
private
Png: TPngImage;
procedure PngReceived;
protected
procedure ClientExecute; override;
end;
type
TInt32Bytes = record
case Integer of
0:
(Bytes: array [0 .. SizeOf(Int32) - 1] of Byte);
1:
(Value: Int32);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
// ===============================================================================
// ===============================================================================
procedure TSock_Thread.PngReceived;
var
Item: TListItem;
begin
Item := Form1.ListView1.Selected;
if (Item <> nil) and (Item.Data = ClientSocket) then
Form1.img1.Picture.Graphic := Png;
end;
procedure TSock_Thread.ClientExecute;
var
SocketStrm: TWinSocketStream;
Buffer: TMemoryStream;
Size: TInt32Bytes;
Offset: Integer;
BytesReceived: Integer;
BufferPtr: PByte;
begin
SocketStrm := TWinSocketStream.Create(ClientSocket, 60);
try
Buffer := TMemoryStream.Create;
try
Png := TPngImage.Create;
try
while ClientSocket.Connected do
begin
if not SocketStrm.WaitForData(100) then
Continue;
Offset := 0;
while Offset < SizeOf(Int32) do
begin
BytesReceived := SocketStrm.Read(Size.Bytes[Offset],
SizeOf(Int32) - Offset);
if BytesReceived <= 0 then
Exit;
Inc(Offset, BytesReceived);
end;
Size.Value := ntohl(Size.Value);
Buffer.Size := Size.Value;
BufferPtr := PByte(Buffer.Memory);
Offset := 0;
while Offset < Size.Value do
begin
BytesReceived := SocketStrm.Read(BufferPtr^, Size.Value - Offset);
if BytesReceived <= 0 then
Exit;
Inc(BufferPtr, BytesReceived);
Inc(Offset, BytesReceived);
end;
Buffer.Position := 0;
try
Png.LoadFromStream(Buffer);
except
Png.Assign(nil);
end;
Synchronize(PngReceived);
end;
finally
Png.Free;
end;
finally
Buffer.Free;
end;
finally
SocketStrm.Free;
end;
end;
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
Item: TListItem;
begin
Item := ListView1.Items.Add;
Item.Caption := IntToStr(Socket.Handle);
Item.SubItems.Add(Socket.RemoteAddress);
Item.SubItems.Add(Socket.RemoteHost);
stat1.Panels.Items[1].Text := 'Conectado';
Item.Data := Socket.Data;
end;
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
var
Item: TListItem;
begin
Item := ListView1.FindData(0, Socket, true, false);
if Item <> nil then
Item.Delete;
stat1.Panels.Items[1].Text := 'Desconectado';
end;
procedure TForm1.ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
ErrorCode := 0;
stat1.Panels.Items[1].Text := 'Erro na conexão';
Socket.Close;
end;
procedure TForm1.ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread);
begin
SocketThread := TSock_Thread.Create(false, ClientSocket);
end;
procedure TForm1.Ativar1Click(Sender: TObject);
begin
ServerSocket1.Active := true;
end;
procedure TForm1.Desativar1Click(Sender: TObject);
begin
ServerSocket1.Active := false;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Form1.DoubleBuffered := true;
end;
procedure TForm1.Foto1Click(Sender: TObject);
var
Index: Integer;
begin
Index := ListView1.ItemIndex;
if Index = -1 then
Exit;
ServerSocket1.Socket.Connections[Index].SendText('screencapture' + #13#10);
end;
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
begin
{ if (Item <> nil) and Selected then
img1.Picture.Assign(TSocketData(TCustomWinSocket(Item.Data).Data).Png); }
end;
procedure TForm1.ServerSocket1Listen(Sender: TObject; Socket: TCustomWinSocket);
begin
stat1.Panels.Items[1].Text := 'Aguardando conexões na porta: ' +
IntToStr(ServerSocket1.Port);
end;
end.