首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >应该调用多少次C# .BeginReceive()才能接收三个块--通过TCP对Linux C写()的3个调用?

应该调用多少次C# .BeginReceive()才能接收三个块--通过TCP对Linux C写()的3个调用?
EN

Stack Overflow用户
提问于 2014-02-15 16:54:16
回答 2查看 675关注 0票数 0

通过TCP对Linux 'C‘write()的3个调用发送的3个块是否被Windows C# .BeginReceive()接收为相同的三个块,还是单个连续块,或者在调用.BeginReceived时收到了多少块?

Linux上的一个'C‘应用程序通过3个调用发送消息,通过TCP连接将()写到一个使用C# ()接收的Windows BeginReceive应用程序。

是否需要调用BeginReceive()三次,以接收write()发送的三个块中的每个块?或者BeginReceive()接收的大小是否等于调用BeginReceive()时所接收的大小?哪个字节可以是3写()发送的所有字节,也可以是部分数量,所以应该调用.BeginReceive(),直到全部接收到为止?

Linux应用程序是在嵌入式TI ARM上运行的,在同一个盒子里,Windows C#应用程序运行的是一台单板计算机。ARM与SBC有一个直接的以太网连接。

ARM和SBC之间的通信有时无法在启动时启动,我正在反向工程源代码以检查错误的设计。

ARM端是TCP侦听器,Windows客户端启动TCP连接。

使用MontaVista(R) Linux(注册商标)专业版5.0.0 (0702774)和Windows7Visual-Studio 2010 Visual#。

这是ARM发送软件和Windows接收软件.

LINX 'C‘

代码语言:javascript
复制
        char msgBuffer[64];
        sprintf(msgBuffer, START_MSG_ENVELOPE, msgId++, ack);
        write(connection->fd, msgBuffer, strlen(msgBuffer));
        write(connection->fd, msg, strlen(msg));
        write(connection->fd, END_MSG_ENVELOPE, strlen(END_MSG_ENVELOPE));

这里是IT.............................................的WINDOWS C#端

代码语言:javascript
复制
        private static void makeConnection(Socket clientSocket, int iPortNo)
    {
        TimeoutObject.Reset();
        socketexception = null;

        IPAddress ip;
        //create the end point 
        IPEndPoint ipEndPoint;

        ip = IPAddress.Parse(ipAddress);

        try
        {
            ipEndPoint = new IPEndPoint(ip, iPortNo);

            //connect to the remote host...
            clientSocket.BeginConnect(ip, iPortNo, new AsyncCallback(CallBackMethod), clientSocket);

            if (TimeoutObject.WaitOne(5 * 1000, false))    //5 secs connection timeout
            {
                if (!IsConnectionSuccessful)
                {
                    string msg = VNResourceManager.Instance.GetString(VNMessages.DAM_NOT_FOUND);
                    if (socketexception != null)
                        msg += ": " + socketexception.Message;
                    throw new Exception(msg);
                }
            }
            else
            {
                clientSocket.Close();
                throw new TimeoutException(VNResourceManager.Instance.GetString(VNMessages.CONNECTION_TO_DAM_TIMED_OUT));
            }
            //watch for data ( asynchronously )...
            WaitForData();
        }
        catch (SocketException e)
        {
            socketexception = e;
            throw;
        }
    }

    private static void CallBackMethod(IAsyncResult asyncresult)
    {
        try
        {
            IsConnectionSuccessful = false;
            Socket socket = asyncresult.AsyncState as Socket;

            if (socket.Connected)
            {
                socket.EndConnect(asyncresult);
                IsConnectionSuccessful = true;
            }
        }
        catch (Exception ex)
        {
            IsConnectionSuccessful = false;
            socketexception = ex;
        }
        finally
        {
            TimeoutObject.Set();
        }
    }

    public static void WaitForData()
    {
        try
        {
            if (asyncCallBack == null)
            {
                asyncCallBack = new AsyncCallback(OnDataReceived);
            }
            CSocketPacket theSocPkt = new CSocketPacket();
            theSocPkt.thisSocket = clientSocket;
            asyncResult = clientSocket.BeginReceive(theSocPkt.dataBuffer, 0, theSocPkt.dataBuffer.Length, SocketFlags.None, asyncCallBack, theSocPkt);
        }
        catch (SocketException se)
        {
            notifyErrorEventSubscribers(se);
        }
    }

    public static void send(string message)
    {
        try
        {
            byte[] byData = System.Text.Encoding.ASCII.GetBytes(message);
            clientSocket.Send(byData);
        }
        catch (SocketException se)
        {
            notifyErrorEventSubscribers(se);
            throw;
        }
    }

    //[MethodImpl(MethodImplOptions.Synchronized)]
    public static void OnDataReceived(IAsyncResult result)
    {
        try
        {
            CSocketPacket theSockId = (CSocketPacket)result.AsyncState;

            //end receive...
            int messageSize = 0;

            messageSize = theSockId.thisSocket.EndReceive(result);

            Console.WriteLine(">>>>>>>>>  messageSize = " + messageSize); // !!!

            char[] chars = new char[messageSize + 1];

            System.Text.Decoder d = System.Text.Encoding.ASCII.GetDecoder();
            int charLen = d.GetChars(theSockId.dataBuffer, 0, messageSize, chars, 0);

            string replyMessage = new System.String(chars);

            lock (syncLock)  //LastIndexOf function accesses the current culture info and we clear it in WM_TIMECHANGE handler (protecting from that race condition here)
            {
                if (replyMessage.LastIndexOf("\0") > 0)
                    replyMessage = replyMessage.Remove(replyMessage.LastIndexOf("\0"), 1);
                if (replyMessage.LastIndexOf(Terminator) > 0)
                    replyMessage = replyMessage.Remove(replyMessage.LastIndexOf(Terminator), 1);
            }


            // Continue the waiting for data on the Socket
            WaitForData();

            receivedMsg += replyMessage;


            // only serialize when we feel we have a message or we have reached the message line limit  
            if (((receivedMsg.Contains("message") && receivedMsg.Contains("/>")) || receivedMsg.Contains("</message>")) /* || (mRecvdMsgLineCount == Message.kMaxLines) */ )
            {
                List<XmlMessage> msgList = new List<XmlMessage>();

                int index = -1;
                do
                {
                    index = receivedMsg.IndexOf("</message>");

                    if (index != -1)
                    {
                        XmlMessage message;
                        string strMessage = receivedMsg.Substring(0, index + "</message>".Length);
                        //MessageBox.Show(strMessage);
                        strMessage = strMessage.TrimStart(new char[] { '\r', '\n' });

                        receivedMsg = receivedMsg.Remove(0, index + "</message>".Length);

                        try
                        {
                            message = (XmlMessage)XmlMessage.GetXmlSerializer().Deserialize(XmlReader.Create(new StringReader(strMessage)));
                        }
                        catch (InvalidOperationException error)
                        {
                            string strErrorMessage = error.Message;
                            if (error.InnerException != null)
                                strErrorMessage += "\r\n" + error.InnerException.Message;

                            notifyErrorEventSubscribers(new Exception(strErrorMessage + "\r\n-----------------------------------------------------------------\r\n" + strMessage));

                            return;
                        }

                        msgList.Add(message);
                    }
                } while (index != -1);

                StringWriter sw = new StringWriter();
                string serializedXml = string.Empty;
                string strXmlMessage = string.Empty;

                foreach (XmlMessage message in msgList)
                {
                    if (message.ack_required && (message.update == null))
                    {
                        XmlMessage messageAcknowledge = new XmlMessage();
                        messageAcknowledge.ack_required = false;
                        messageAcknowledge.ack = new ack();
                        messageAcknowledge.ack.success = true;
                        messageAcknowledge.ack.id = message.id;

                        try
                        {
                            sendMessage(messageAcknowledge);
                        }
                        catch(Exception ex)
                        {
                            Logger.Log(EnumLoggingLevel.Error, "SocketCommunicationXMl.OnDataReceived", ex.Message);
                        }
                    }

                    if (dataReceivedEvent != null)
                    {
                        dataReceivedEvent(new object(), new DataReceivedEventArgs(message));
                    }

                    if ((ackRequiredMsg != null) && (message.ack != null))
                    {
                         if ((message.ack.id == ackRequiredMsg.id) && message.ack.success)
                         {
                             eventWaitForAck.Set();
                         }
                    }
                }
            }
        }
        catch (ObjectDisposedException objectDisposedException)
        {
            //              Dispatcher.dispatchDebug(Debug.Level_3,"Socket has been closed", this);
            notifyErrorEventSubscribers(objectDisposedException);
        }
        catch (SocketException se)
        {
            if (se.ErrorCode == 10054)
            {
                /*
                for (int i = 0; i < 50; i++)
                {
                    Thread.Sleep(1000);
                }

                try
                {
                    SocketCommunicationDaq.Reconnect();
                }
                catch(Exception ex)
                {
                    VNMsgBox.Show(ex.Message, MsgButtonType.OkOnly, MsgIconType.Error);
                    return;
                }

                clientSocket.Shutdown(SocketShutdown.Both);
                clientSocket.Close();

                for (int i = 0; i < 3; i++)
                {
                    try
                    {
                        connect();
                        break;
                    }
                    catch (Exception ex)
                    {
                        System.Threading.Thread.Sleep(5000);
                    }
                }
                */
                Logger.Log(EnumLoggingLevel.Error, "OnDataReceived: ", se.ToString());
            }
            else
            {
                notifyErrorEventSubscribers(se);
            }
        }
    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-18 16:52:22

正如其他人所提到的,TCP是一种流协议,因此您永远无法知道获得全部100个字节需要多少DataReceived回调。可能是1,可能是100。

接收代码相当复杂,性能可以提高(太多的字符串操作)。很难说是否存在控制流问题。我建议打破DataReceived方法来简化。这里有一个合理的骨架:

代码语言:javascript
复制
    public static void OnDataReceived(IAsyncResult result)
    {
        //1) copy all data received into a buffer of some sort, like MemoryStream

        //2) Dispatch any/all full messages that have been received
          // to a queue or handler method (maybe handle on another thread)
          //(hold onto any leftover bytes received that are part of the next message)

        //Call BeginReceive() again
    }

此外,如果您使用长度前缀消息格式,则可以帮助简化框架设置。

票数 1
EN

Stack Overflow用户

发布于 2014-02-16 11:15:28

正如@nos已经指出的那样,接收的数量并不等于发送的数量,而不管客户端应用程序是在什么情况下写入的。

另见When does TcpClient's NetworkStream finish one read operation?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21800665

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档