我有一些接收一系列消息的代码:
byte[] buffer = new byte[10240];
//...
sock.Receive(buffer);
string response = message(buffer);
Console.WriteLine("Message Recieved");
if (!verifyUser(response, sock))
Console.WriteLine("User Invalid");
//...
static private bool verifyUser(string userString, Socket sock)
{
string[] userData = userString.Split(' ');
int i = 0;
while (true)
{
if (userData[0].ToUpper() != "USER")
{
byte[] buffer = message("WHO");
sock.Send(buffer);
userData = userString.Split(' ');
i++;
if (i > 4)
{
return false;
}
continue;
}
else
break;
}
Console.WriteLine("Connection recieved from " + userData[1] + " with hash of "/* + userData[2]*/);
}
我遇到的问题是,如果我提交用户名unkwntech所有显示的内容都是unkwnt,第二个值似乎永远不会到达那里。 发送数据的应用程序如下所示:
static void Main(string[] args)
{
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
EndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 200);
sock.Connect(remoteEP);
byte[] buffer = Encoding.ASCII.GetBytes("USER unkwntech a3f5h4a35sfg");//Made up hash
sock.Send(buffer);
sock.Receive(buffer);
Console.WriteLine(Encoding.ASCII.GetString(buffer));
Console.ReadLine();
}
答案 0 :(得分:7)
你假设发送时,所有数据都以一个数据包结束,并且你将在另一端收到所有数据。这不是TCP / IP的工作原理。这是一个流媒体协议 - 你永远不应该假设你一次会收到多少数据。
基本上你需要从流中读取,直到你已经读完所有数据并且套接字已经关闭,或者直到你得到“足够”的数据。如果您控制协议并且它是一个会话协议,那么如果您发送的每条消息都以其长度为前缀,则会使生活变得更加容易 - 这意味着另一端知道预期会有多少数据。
答案 1 :(得分:1)
检查Socket.Receive调用的返回值。它返回接收的字节数。您可以将此调用放在循环中并读取,直到获得您期望的字节数。您还应该通过设置最大尝试次数来防止无限循环,或者如John建议的那样,检查套接字的状态。此外,不要假设返回值为零意味着您已阅读整个消息。
如果您的协议的每个消息都以其长度为前缀,那么为了真正防弹,您的协议还应该定义一个标记字节来标记前缀长度标头的末尾。一次读取一个字节,直到看到标记字节。然后计算消息的长度并以更大的块读取,直到您全部读完为止。
Socket.Receive定义了一个重载,它允许您指定要接收的字节数。 (但是,您不能保证会收到那么多,所以您仍然需要检查返回值。)