如何在ThreadBlocking模式下接收客户端连接?

问题描述 投票:0回答:1

我想在一个线程内的服务器上收到一个截图,并试图使用在一个实验成员(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.
multithreading sockets delphi
1个回答
1
投票

现在我想知道(主要是一个Android程序员)如果在客户端(Android)Socket也必须在ThreadBlocking中建立这个连接成功

阻止与非阻塞完全是本地设计选择,它根本不会对底层通信产生影响。非阻塞客户端可以与阻塞服务器通信,反之亦然。

© www.soinside.com 2019 - 2024. All rights reserved.