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

标签 c# sockets asynchronous synchronous

我在使用两个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);
            }
        }

问题是,当我从客户端向同步服务器发送图片时,一切正常,服务器收到了图片,但是如果我从同一客户端向异步服务器发送图片,则图片没有收到。

最佳答案

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

TCP流数据,这意味着您可以按发送的顺序读取到达的数据,但是发送1000字节并不意味着您将立即接收1000字节。您甚至可以在一个Receive操作中从两个不同的消息中接收数据。您发送的数据越多,发送数据的次数越多,发生这种影响的机会就越大。

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

  • 您可以选择在发送每个图像后让客户端断开连接,因为异步服务器当前期望
  • 您可以选择先发送图像的字节数,然后再发送图像数据本身。确保尺寸本身以固定长度编码。这样可以避免您始终保持重新连接,还可以预先确定接收缓冲区
  • 的大小。
  • 或者您可以使用base64范围之外的字节来分隔数据,但这需要扫描接收到的数据
  • 关于c# - C#-异步服务器与同步服务器-套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38904696/

    相关文章:

    c# - 将属性(名称=值)从 MSBuild 项目写入文件

    c# - 建议查询时间长

    c# - GZipStream 和 DeflateStream 产生更大的文件

    java - 套接字复位是什么原因

    javascript - 如何使用 mocha.js 测试多个异步流程事件

    c# - C# 桌面应用程序许可证

    javascript - Node 套接字挂断错误与http

    javascript - asyn vs sync forEach,map,filter

    c# - 在异步任务和 UI 线程中提高 PropertyChanged

    java - 服务器在客户端-服务器应用程序中未收到消息