通过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‘
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#端
private static void makeConnection(Socket clientSocket, int iPortNo) TimeoutObject.Reset(); socketexception = null; IPAddress ip; //create the end point IPEndPoint ipEndPoint; ip = IPAddress.Parse(ipAddress); 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); 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) 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() 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) 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) 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; 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); 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; 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); 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++) connect(); break; catch (Exception ex) System.Threading.Thread.Sleep(5000); Logger.Log(EnumLoggingLevel.Error, "OnDataReceived: ", se.ToString()); notifyErrorEventSubscribers(se); }
发布于 2014-02-18 16:52:22
正如其他人所提到的,TCP是一种流协议,因此您永远无法知道获得全部100个字节需要多少DataReceived回调。可能是1,可能是100。
接收代码相当复杂,性能可以提高(太多的字符串操作)。很难说是否存在控制流问题。我建议打破DataReceived方法来简化。这里有一个合理的骨架:
public static void OnDataReceived(IAsyncResult result) //1) copy all data received into a buffer of some sort, like MemoryStream