我想在一个线程内的服务器上收到一个截图,并试图使用在一个实验成员(Delphi程序员)的this answer中建议的代码,第二个他,这个代码只能在ThreadBlocking
模式下工作。
我已经将TServerSocket
(Delphi组件)放在这种模式下,但是当组件处于这种模式时,无法在服务器上从用Java制作的客户端(也使用Socket
建立此连接)接收任何连接。
现在我想知道(主要是一个Android程序员)如果在客户端(Android)Socket
也必须在ThreadBlocking
中建立这个连接成功,或者所有这些工作缺少什么,应该如何?
以下是我的代码的两部分:
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.
现在我想知道(主要是一个Android程序员)如果在客户端(Android)Socket也必须在ThreadBlocking中建立这个连接成功
阻止与非阻塞完全是本地设计选择,它根本不会对底层通信产生影响。非阻塞客户端可以与阻塞服务器通信,反之亦然。