我对这里发生的事情感到非常困惑。我一直在提供突破点,而我似乎无法理解。基本上,我有一个客户端和一个服务器。我希望客户端发送两个单独的数据字符串。从提交断点开始,我注意到我的客户端确实用适当的数据填充了两个字符串。但是,服务器永远不会看到第二个字符串。为什么会发生这种情况,我该如何解决?任何帮助都会非常感激!以下是我的代码:
服务器:
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); 我得到一个IOException错误,其内容如下:无法将数据写入传输连接:远程主机强制关闭现有连接。因此,我将其更改为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();
}
}
答案 0 :(得分:2)
因为while (clientStream.DataAvailable)
在第一次客户电话后不再为真。
答案 1 :(得分:2)
客户端和服务器之间的通信发生如下(请注意,步骤的顺序仅用于说明目的,运行时的实际顺序可能不同):
客户:client.Connect(serverEndPoint)
服务器:HandleClientComm(newClient)
客户:clientStream.Write(buffer, 0, buffer.Length)
服务器:bytesRead = clientStream.Read(message, 0, message.Length)
请注意,Read
无法保证读取整个邮件。只返回到目前为止收到的部分是完全可以的
客户:Console.ReadLine()
服务器:while (clientStream.DataAvailable)
流上没有数据 - 客户端没有发送任何数据。即使没有ReadLine
,也可能发生这种情况 - 客户端再次发送数据之前有一段时间
服务器: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);
}
协议很简单,可能适合您的情况。但是,它存在一些问题,应该在生产代码中解决(例如,如果客户端发送过多数据,耗尽服务器内存,如果客户端在不关闭连接的情况下停止发送会怎么样,等等)。
答案 2 :(得分:1)
您正在退出服务器中的client-recv循环,因为DatAvailable为false。这意味着如果客户端要发送一个数据帧(您使用的数据)并暂停,那么您的服务器将在那时看不到可用的数据并断开连接,即使一秒钟之后客户端的另一帧数据即将到来几乎总是,对话框的结束基于传递的数据的内容。你当然可以永远不要试图依赖DataAvailable碰巧错误的事实。
作为后续行动,如果您提供有关所使用协议的更多信息,我们可以提供更多帮助。例如,如果prototcol是最后两个字符串与CR / LF一起发送的那么服务器循环应该检查缓冲区以确定何时断开连接。