我怎样才能收到消息

时间:2016-07-01 09:06:39

标签: c# sockets timeout recv

我正在维护一个C#系统,其中一部分工作是从随机客户端接收tcp消息(使用socket.recv())。我们确实有一个消息协议,以便外部开发人员可以填充格式良好的消息。

消息格式如下:

{ public data(fixed length):private data(variable length) }

要接收消息,我们需要此消息中的私有数据长度字段,但有人需要发送可能填写错误长度编号的消息。如何满足此要求?

这是我的代码:

public static int ReceiveMessage(int totalByteNumber, Socket socket, byte[] recvBuffer)
{
  try
  {
    int offset = 0;
    do
    {
      try
      {
        int num = socket.Receive(recvBuffer, offset, totalByteNumber - offset, SocketFlags.None);
        if (num == 0)
        {
          throw new ApplicationException();
        }
        offset += num;
      }
      catch (SocketException ex)
      {
        if (ex.SocketErrorCode == SocketError.IOPending || ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
          Thread.Sleep(30);
        else if (ex.SocketErrorCode == SocketError.WouldBlock)
        {
          socket.Blocking = true;
          Thread.Sleep(30);
        }
        else
        {
          LogManager.WriteError("Origin IP:" + (object) ((IPEndPoint) socket.RemoteEndPoint).Address);
          throw ex;
        }
      }
    }
    while (offset < totalByteNumber);
    return offset;
  }
  finally
  {
    SocketUtility.LogMessage("Recv", recvBuffer, socket);
  }
}

1 个答案:

答案 0 :(得分:0)

您无法容纳格式错误的消息,至少不可靠。 TCP不保持消息边界,因此您无法知道发送给您的消息有多长。

实际上,如果您通常有短请求并且请求者在一个发送系统调用中发送整个请求,则每次接收很可能只返回一个请求消息,但这不可靠。例如,如果请求者将两个背靠背发送给您,则可能会在您的进程安排之前合并它们,以便在一次接收呼叫中将两者都返回给您。

您的选择:

  • 消息中的长度字段,告诉您预期多少(大多数二进制协议以这种方式工作)
  • 消息中的一些标志模式(空字节,或空行文本,或其他;基于文本的协议,如HTTP通常以这种方式工作)
  • 文件结束(即来电者可以发送请求,然后拨打socket.Shutdown(Send);,你就会得到EOF,并且知道这一切都是期待的;显然是这样的一次性交易)