TCP服务器无法从套接字读取,直到处理掉的对象

时间:2009-11-24 14:16:08

标签: .net vb.net sockets tcp

请原谅我选择的措辞和/或术语混淆,在套接字编程方面我是个假人。我正在尝试连接到TCP服务器,编写消息并处理响应。我使用以下代码:

Dim tcpClient As Sockets.TcpClient = New TcpClient()

tcpClient.Connect(hostname, 9080)

Dim networkStream As NetworkStream = tcpClient.GetStream()

If networkStream.CanWrite And networkStream.CanRead Then

    Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes(body)
    networkStream.Write(sendBytes, 0, sendBytes.Length)

    Dim bytes(tcpClient.ReceiveBufferSize) As Byte
    networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))

    Dim returndata As String = Encoding.ASCII.GetString(bytes)
End If

我可以看到服务器日志,并注意到当我停止调试时服务器只从套接字中读取。然后它处理消息并发送响应(这有点晚了我的客户端不再听了)

似乎需要首先关闭networkStream对象。但是,如果我这样做,我无法处理任何后续响应。我是否需要向已完成写入的服务器“发信号”?我是否需要完全使用其他型号?

1 个答案:

答案 0 :(得分:1)

关闭/处置NetworkStream不是必需的,但我会质疑数据的发送方式。你写过服务器了吗?我希望发送(和接收)数据的长度前缀或终止字符或短语。如果您只是编写这样的数据,服务器就无法知道它应该读取多少数据。

接收代码也是如此。您只是尝试阅读ReceiveBufferSize,而不是使用服务器发送给您的长度。

您确定您使用的协议不包含这些元素吗?

另外,请记住Read和大多数/所有其他Stream个对象一样,保证您将获得所请求的字节数。它将读取最多该字节数,函数的返回值表示读取了多少。您通常必须设置循环结构以获取特定数字。有点像...

int bytesToRead = 1024; // sample
int totalBytesRead = 0;
int bytesRead = 0

while(bytesToRead > 0)
{
    bytesRead = stream.Read(buffer, totalBytesRead, bytesToRead);

    if(bytesRead == 0) throw new Exception("Connection closed");

    totalBytesRead += bytesRead;
    bytesToRead -= bytesRead;
}

这比典型的实现更冗长,让您了解需要发生的事情。更典型的是:

int bytesToRead = 1024;
int bytesRead = 0;

while((bytesRead += stream.Read(buffer, bytesRead, bytesToRead - bytesRead) <= bytesToRead - bytesRead) { }