c#客户端/服务器问题
本文关键字:问题 服务器 客户端 | 更新日期: 2023-09-27 18:09:37
我对这里发生的事情感到非常困惑。我一直在输入断点,但我就是不明白。基本上,我有一个客户端和一个服务器。我希望客户端发送数据的两个单独的字符串。通过放入断点,我注意到我的客户端实际上用适当的数据填充了两个字符串。但是,服务器永远不会看到第二个字符串。为什么会发生这种情况,我该如何解决?任何帮助都将非常感激!下面是我的代码:
服务器:
private static void HandleClientComm(object client)
{
/** creating a list which contains DatabaseFile objects **/
List<DatabaseFile> theDatabase = new List<DatabaseFile>();
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
StringBuilder response = new StringBuilder();
byte[] message = new byte[4096];
int bytesRead;
do
{
bytesRead = 0;
try
{
/*do
{
bytesRead = clientStream.Read(message, 0, message.Length);
response.Append(Encoding.ASCII.GetString(message, 0, bytesRead));
} while (clientStream.DataAvailable);*/
当我改变这个注释代码bytesRead = clientStream。Read(message, 0,4096); i get a IOException Error,内容如下:cannot to write data to the transport connection:一个已存在的连接被远端主机强制关闭。因此,我将其更改为do while循环。我如何绕过这个IOException并接受第二个字符串?
ASCIIEncoding encoder = new ASCIIEncoding();
String file = encoder.GetString(message, 0, bytesRead);
Menu.Insert(theDatabase, file);
}
catch (Exception)
{
// A socket error has occured
break;
}
if (bytesRead == 0)
{
// The client has disconnected from the server
break;
}
} while (clientStream.DataAvailable);
// Release connections
clientStream.Close();
tcpClient.Close();
}
客户:
static void Main(string[] args)
{
TcpClient client = new TcpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
client.Connect(serverEndPoint);
NetworkStream clientStream = client.GetStream();
NetworkStream clientStream2 = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
ASCIIEncoding encoder2 = new ASCIIEncoding();
String text = System.IO.File.ReadAllText("FirstNames.txt");
String text2 = System.IO.File.ReadAllText("LastNames.txt");
byte[] buffer = encoder.GetBytes(text);
Console.ReadLine();
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
Console.ReadLine();
byte[] buffer2 = encoder2.GetBytes(text2);
clientStream2.Write(buffer2, 0, buffer2.Length);
clientStream2.Flush();
Console.ReadLine();
}
}
客户机和服务器之间的通信是这样进行的(注意步骤的顺序只是为了说明,运行时的实际顺序可能不同):
-
客户端:
client.Connect(serverEndPoint)
服务器:HandleClientComm(newClient)
-
Client:
clientStream.Write(buffer, 0, buffer.Length)
服务器:bytesRead = clientStream.Read(message, 0, message.Length)
注意,Read
不能保证读取整个消息。只返回到目前为止已经接收到的部分是完全可以的 -
Client:
Console.ReadLine()
Server:while (clientStream.DataAvailable)
流上没有数据-客户端没有发送任何数据。即使没有ReadLine
,这种情况也可能发生——在客户端再次发送数据之前有一个时间窗口 -
Server:
tcpClient.Close()
- 客户端:
clientStream2.Write(buffer2, 0, buffer2.Length)
你可以在这里得到一个异常,或者没有-取决于服务器是否已经关闭连接,在任何情况下,服务器不再读取
您需要定义您自己的消息协议,服务器和客户端都将遵守该协议。例如,您可以让客户端在完成发送时关闭连接:
客户:using (var client = new TcpClient("localhost", 8888))
using (var clientStream = client.GetStream())
{
var buffer = Encoding.ASCII.GetBytes( File.ReadAllText("FirstNames.txt") );
clientStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes( File.ReadAllText("LastNames.txt") );
clientStream.Write(buffer, 0, buffer.Length);
}
服务器:
using (var tcpClient = (TcpClient)client)
using (var clientStream = tcpClient.GetStream())
{
// Store everything that the client sends.
// This will work if the client closes the connection gracefully
// after sending everything
var receivedData = new MemoryStream();
clientStream.CopyTo(receivedData);
var rawBytes = receivedData.ToArray();
var file = Encoding.ASCII.GetString(rawBytes, 0, rawBytes.Length);
Menu.Insert(theDatabase, file);
}
协议很简单,可能对你的情况足够了。然而,它有一些问题应该在生产代码中解决(例如,如果客户端发送太多数据,耗尽服务器内存,如果客户端在没有关闭连接的情况下停止发送怎么办,等等)
因为while (clientStream.DataAvailable)
在您的第一个客户端调用后不再为真。
退出服务器中的client-recv循环,只是因为DatAvailable为false。这意味着,如果客户端发送一帧数据(您正在使用)并暂停,那么您的服务器将在那一刻看到没有可用的数据并断开连接,即使在一瞬间之后来自客户端的另一帧数据即将进入。对话框的结束几乎总是基于所传递的数据的内容。当然,您永远不能指望DataAvailable恰好有一次为假。
接下来,如果你能提供更多关于使用的协议的信息,我们可以提供更多的帮助。例如,如果协议是两个字符串以CR/LF结尾发送,那么服务器循环应该检查缓冲区,以知道何时断开。