c# -异步服务器vs同步服务器-套接字

本文关键字:服务器 套接字 同步 vs 异步 | 更新日期: 2023-09-27 18:02:06

我有一些奇怪的问题,两个c#服务器套接字。

我有2台服务器。一个是异步的,另一个是同步的。我也有客户端在android发送图片到这个服务器。

同步服务器:

Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public void Start()
{
    byte[] bytes = new Byte[1024000];
    String content = String.Empty;
    IPAddress ipAddress = IPAddress.Parse("192.168.1.2");
    IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 53100);
    try
    {
        listener.Bind(localEndPoint);
        listener.Listen(10);
        while (true)
        {
            //// Program is suspended while waiting for an incoming connection.
            Socket handler = listener.Accept();
            data = null;
            // An incoming connection needs to be processed.
            while (true)
            {
                bytes = new byte[1024000];
                int bytesRec = handler.Receive(bytes);
                strBuilder.Append(Encoding.ASCII.GetString(bytes, 0, bytesRec));
                if (strBuilder.Length > 1)
                {
                    content = strBuilder.ToString();
                    byte[] xdata = Convert.FromBase64String(content);
                    using (var mStream = new MemoryStream(xdata, 0, xdata.Length))
                    {
                        pictureBox1.Image = Image.FromStream(mStream, true);
                    }
                }
            }
            byte[] msg = Encoding.ASCII.GetBytes(data);
            handler.Send(msg);
            handler.Shutdown(SocketShutdown.Both);
            handler.Close();
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}
private void Form1_Load(object sender, EventArgs e)
{
    thr = new Thread(new ThreadStart(Start));
    thr.Start();
}
异步服务器:

public void StartListening()
        {
            listener.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.2"), 53100));
            listener.Listen(1);
            allDone.Reset();
            listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
        }
        public void AcceptCallback(IAsyncResult ar)
        {
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);
            StateObject stateObj = new StateObject();
            stateObj.clientSocket = handler;
            handler.BeginReceive(stateObj.buffer, 0, StateObject.buffSize, 0, 
                new AsyncCallback(ReadCallback), stateObj);
            listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
        }
        public void ReadCallback(IAsyncResult ar)
        {
            String content = String.Empty;
            StateObject stateObj = (StateObject)ar.AsyncState;
            Socket handler = stateObj.clientSocket;
            SocketError errorCode;
            int bytesRead = handler.EndReceive(ar, out errorCode);
            if (errorCode != SocketError.Success)
            {
                bytesRead = 0;
            }
            if (bytesRead > 0)
            {
                stateObj.strBuilder.Append(Encoding.ASCII.GetString(stateObj.buffer, 0, bytesRead));
                handler.BeginReceive(stateObj.buffer, 0, stateObj.buffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), stateObj);
            }
            else
            {
                if (stateObj.strBuilder.Length > 1)
                {
                    content = stateObj.strBuilder.ToString();
                    Debug.WriteLine(content);
                    byte[] data = Convert.FromBase64String(content);
                    using (var mStream = new MemoryStream(data, 0, data.Length))
                    {
                        pictureBox1.Image = Image.FromStream(mStream, true);
                    }
                    recImage = (Bitmap)pictureBox1.Image;
                    imgImage = new Image<Bgr, Byte>(recImage);
                    imageBox1.Image = imgImage;
                    while (imageBox1.Image != null)
                    {
                        SURFDetectionAndGUIUpdate(this, new EventArgs());
                    }
                    string xname = name.ToString();
                    Send(handler, xname);
                }
            }
        }
        private void Send(Socket handler, String data)
        {
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            handler.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback(SendCallback), handler);
        }
        private void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket handler = (Socket)ar.AsyncState;
                int bytesSent = handler.EndSend(ar);
                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

问题是,当我从客户端发送图片到同步服务器,一切工作和服务器接收它,但如果我从同一个客户端发送图片到异步服务器,它不接收它。

c# -异步服务器vs同步服务器-套接字

当前您的同步服务器尝试从第一个Receive的数据创建位图,异步服务器等待,直到客户端断开连接,然后尝试从数据创建位图。

TCP 流式传输数据,这意味着你可以在数据到达时按照发送的顺序读取数据,但是发送1000字节并不意味着你会一次收到1000字节。您甚至可以在单个Receive操作中从两个不同的消息接收数据。发送的数据越多,发送数据的次数越多,发生这种效应的可能性就越大。

在评论中,你提到客户端将发送多个图像,所以在你继续之前,你应该决定如何确定何时接收第一个图像以及何时开始接收第二个图像的数据:

  • 您可以选择让客户端在发送每个图像后断开连接,因为异步服务器当前期望
  • 您可以选择在发送图像数据本身之前先发送图像的字节数。确保大小本身以固定长度编码。这可以防止您一直重新连接,并且还允许您预先确定接收缓冲区的大小
  • 或者您可以使用base64范围之外的字节来分隔数据,但这需要扫描接收到的数据