如何使用单个 TcpClient 实例从客户端向服务器发送多条字符串消息?
How can I send multiple string messages from client to server using a single instance of TcpClient?
我有单独的客户端和服务器控制台应用程序。我只是想从客户端向服务器发送一个字符串,并让服务器使用 TcpClient 将字符串写入控制台。我可以很好地发送一条消息,但是当我将 while
循环放入客户端应用程序以尝试在不关闭 TcpClient 的情况下发送多条消息时,服务器不会向控制台写入任何内容。
//Server
using (TcpClient client = listener.AcceptTcpClient())
{
NetworkStream ns = client.GetStream();
byte[] buffer = new byte[1024];
while (true)
{
if (ns.DataAvailable)
{
int bytesRead = 0;
string dataReceived = "";
do
{
bytesRead = ns.Read(buffer, 0, buffer.Length);
dataReceived += Encoding.UTF8.GetString(buffer, 0, bytesRead);
}
while (bytesRead > 0);
Console.WriteLine($"Message:{ dataReceived }\n");
}
}
}
//Client
using (TcpClient client = new TcpClient(hostname, port))
{
if (client.Connected)
{
Console.WriteLine("Connected to server");
NetworkStream ns = client.GetStream();
string message = "";
//Removing this while loop I can send a single message that the server will write to console
//but with the loop present the server does not write anything
while (true)
{
message = Console.ReadLine();
byte[] messageBytes = UTF8Encoding.UTF8.GetBytes(message);
ns.Write(messageBytes);
Console.WriteLine($"Message Sent! ({ messageBytes.Length } bytes)");
}
}
}
我对学习套接字很感兴趣,两天来一直在研究 SO 问题和 MSDN 文档,但无法弄清楚为什么它没有按我的预期工作。我什至觉得提交问题有点傻,因为我确定这是我不理解的基本问题。有人可以给我一些知识吗?
解决方案
//Server
using (TcpClient client = listener.AcceptTcpClient())
{
NetworkStream ns = client.GetStream();
StreamReader sr = new StreamReader(ns);
string message = "";
while (true)
{
message = sr.ReadLine();
Console.WriteLine(message);
}
}
//Client
using (TcpClient client = new TcpClient(hostname, port))
{
if (client.Connected)
{
Console.WriteLine("Connected to server");
NetworkStream ns = client.GetStream();
StreamWriter sw = new StreamWriter(ns) {Autoflush = true};
string message = "";
while (true)
{
message = Console.ReadLine();
sw.WriteLine(message);
}
}
}
如果您调试服务器,您会发现它确实接收到数据。您只是没有显示数据,因为您的服务器唯一的输出是在返回的字节数为 0 的循环之后:Console.WriteLine($"Message:{ dataReceived }\n");
。当底层套接字已关闭时,字节数将仅为 0。这永远不会发生,因为您的客户端陷入了无限循环。
对于像这样的简单的基于文本的 client/server 示例,更好的方法是将 StreamWriter
和 StreamReader
与基于行的消息一起使用,即 WriteLine()
和 ReadLine()
。然后换行符作为消息分隔符,您的服务器可以在每次收到新行时写入消息。
另请注意,在上面的示例中,您假设每个数据块仅包含完整字符。但是您使用的是 UTF8,其中字符可以是两个或更多字节,而 TCP 不保证发送的字节是如何分组的。使用 StreamWriter
和 StreamReader
也会修复这个错误,但如果你想自己明确地这样做,你可以使用 Decoder
class,它将缓冲部分字符。
有关如何正确实施像这样的简单 client/server 网络程序的一些示例,请参阅以下帖子:
.NET Simple chat server example
C# TcpClient: Send serialized objects using separators?
我有单独的客户端和服务器控制台应用程序。我只是想从客户端向服务器发送一个字符串,并让服务器使用 TcpClient 将字符串写入控制台。我可以很好地发送一条消息,但是当我将 while
循环放入客户端应用程序以尝试在不关闭 TcpClient 的情况下发送多条消息时,服务器不会向控制台写入任何内容。
//Server
using (TcpClient client = listener.AcceptTcpClient())
{
NetworkStream ns = client.GetStream();
byte[] buffer = new byte[1024];
while (true)
{
if (ns.DataAvailable)
{
int bytesRead = 0;
string dataReceived = "";
do
{
bytesRead = ns.Read(buffer, 0, buffer.Length);
dataReceived += Encoding.UTF8.GetString(buffer, 0, bytesRead);
}
while (bytesRead > 0);
Console.WriteLine($"Message:{ dataReceived }\n");
}
}
}
//Client
using (TcpClient client = new TcpClient(hostname, port))
{
if (client.Connected)
{
Console.WriteLine("Connected to server");
NetworkStream ns = client.GetStream();
string message = "";
//Removing this while loop I can send a single message that the server will write to console
//but with the loop present the server does not write anything
while (true)
{
message = Console.ReadLine();
byte[] messageBytes = UTF8Encoding.UTF8.GetBytes(message);
ns.Write(messageBytes);
Console.WriteLine($"Message Sent! ({ messageBytes.Length } bytes)");
}
}
}
我对学习套接字很感兴趣,两天来一直在研究 SO 问题和 MSDN 文档,但无法弄清楚为什么它没有按我的预期工作。我什至觉得提交问题有点傻,因为我确定这是我不理解的基本问题。有人可以给我一些知识吗?
解决方案
//Server
using (TcpClient client = listener.AcceptTcpClient())
{
NetworkStream ns = client.GetStream();
StreamReader sr = new StreamReader(ns);
string message = "";
while (true)
{
message = sr.ReadLine();
Console.WriteLine(message);
}
}
//Client
using (TcpClient client = new TcpClient(hostname, port))
{
if (client.Connected)
{
Console.WriteLine("Connected to server");
NetworkStream ns = client.GetStream();
StreamWriter sw = new StreamWriter(ns) {Autoflush = true};
string message = "";
while (true)
{
message = Console.ReadLine();
sw.WriteLine(message);
}
}
}
如果您调试服务器,您会发现它确实接收到数据。您只是没有显示数据,因为您的服务器唯一的输出是在返回的字节数为 0 的循环之后:Console.WriteLine($"Message:{ dataReceived }\n");
。当底层套接字已关闭时,字节数将仅为 0。这永远不会发生,因为您的客户端陷入了无限循环。
对于像这样的简单的基于文本的 client/server 示例,更好的方法是将 StreamWriter
和 StreamReader
与基于行的消息一起使用,即 WriteLine()
和 ReadLine()
。然后换行符作为消息分隔符,您的服务器可以在每次收到新行时写入消息。
另请注意,在上面的示例中,您假设每个数据块仅包含完整字符。但是您使用的是 UTF8,其中字符可以是两个或更多字节,而 TCP 不保证发送的字节是如何分组的。使用 StreamWriter
和 StreamReader
也会修复这个错误,但如果你想自己明确地这样做,你可以使用 Decoder
class,它将缓冲部分字符。
有关如何正确实施像这样的简单 client/server 网络程序的一些示例,请参阅以下帖子:
.NET Simple chat server example
C# TcpClient: Send serialized objects using separators?