1

我在弄清楚为什么我只收到来自我的计算机上运行的服务器应用程序(LocalHost)的一个回复时遇到了一些麻烦。我没有此服务器应用程序的源代码,但它是一个 java 应用程序。发送的消息是 xml 结构,并且必须以 EoT 标记结尾。

通讯:

  1. 客户端连接到服务器。
  2. 客户端向服务器发送消息。
  3. 服务器将收到的消息发送给客户端。
  4. 客户端向服务器发送消息。
  5. 服务器发送一个传输结束字符。
  6. 客户端向服务器发送消息。
  7. 服务器发送一个传输结束字符。

这是我的客户端连接、发送和接收的方式:

public bool ConnectSocket(string server, int port)
{
System.Net.IPHostEntry hostEntry = null;

    try
    {
        // Get host related information.
        hostEntry = System.Net.Dns.GetHostEntry(server);
    }
    catch (System.Exception ex)
    {
            return false;
    }


    // Loop through the AddressList to obtain the supported AddressFamily. This is to avoid
    // an exception that occurs when the host IP Address is not compatible with the address family
    // (typical in the IPv6 case).
    foreach (System.Net.IPAddress address in hostEntry.AddressList)
    {
            System.Net.IPEndPoint ipe = new System.Net.IPEndPoint(address, port);
            System.Net.Sockets.Socket tempSocket = new System.Net.Sockets.Socket(ipe.AddressFamily, System.Net.Sockets.SocketType.Stream, 
                                                                                 System.Net.Sockets.ProtocolType.Tcp);
            tempSocket.Connect(ipe);

            if (tempSocket.Connected)
            {
                m_pSocket = tempSocket;
                m_pSocket.NoDelay = true;
                return true;
            }
            else
                continue;
        }
        return false;
    }
}

public void Send(string message)
{
    message += (char)4;//We add end of transmission character
    m_pSocket.Send(m_Encoding.GetBytes(message.ToCharArray()));
}

private void Recive()
{
    byte[] tByte = new byte[1024];
    m_pSocket.Receive(tByte);
    string recivemessage = (m_Encoding.GetString(tByte));
}
4

1 回答 1

3

您的Receive代码看起来非常错误;您永远不应该假设数据包以与服务器发送消息相同的结构到达 - TCP 只是一个流。所以:您必须从 , 中捕获返回Receive,以查看您收到了多少字节。它可以是一条消息的一部分、一条完整的消息、多条完整的消息,或者是一条消息的后半部分和下一条消息的前半部分。通常,您需要某种“框架”决策,这可能意味着“消息由 LF 字符分割”,或者可能意味着“每条消息的长度以网络字节顺序整数为前缀,4 个字节”。这通常意味着你需要缓冲直到你有一个完整的帧,担心缓冲区末尾的备用数据是下一帧的一部分。但是要添加的关键位:

int bytes = m_pSocket.Receive(tByte);
// now process "bytes" bytes **only** from tByte, nothing that this
// could be part of a message, an entire message, several messages, or
// the end of message "A", the entire of message "B", and the first byte of
// message "C" (which might not be an entire character)

特别是,对于文本格式,在确定缓冲了整个消息之前,您无法开始解码,因为多字节字符可能会在两条消息之间拆分。

您的接收循环中也可能存在问题,但您没有显示(没有调用Receive),因此我们无法发表评论。

于 2012-06-11T08:53:38.533 回答