我正在为通过GPRS连接的生物识别指纹设备编写服务器。服务器从设备接收GET和POST请求,然后执行所需的操作。
通过POST请求,设备应该将一些额外的数据附加到请求中。
问题是,当我通过LAN将设备连接到服务器时,所有数据都很好。当我通过GPRS连接时,我的服务器无法接收请求正文。
在左边,当我通过LAN连接时......消息的主体被附加。在右边,通过GPRS,一切都保持不变,然而,没有身体。
我通过局域网和GPRS连接运行Wireshark。这些数据包,当我向下钻取时,都有附着的身体,但在Wireshark上,通过GPRS,我得到上面的消息 - 乱序,RST,ACK和有时PSH,ACK。
与没有这些问题的LAN数据包形成对比。
这是我用来从TCPListener
中读取的代码try
{
if (tcp == null)
{
this.tcp = new TcpListener(IPAddress.Parse(serverIP), port);
}
this.tcp.Start();
listening = true;
while (listening)
{
Socket mySocket = null;
// Blocks until a client has connected to the server
try
{
mySocket = this.tcp.AcceptSocket();
Thread.Sleep(500);
byte[] bReceive = new byte[1024 * 1024 * 2];
mySocket.Receive(bReceive);
Analysis(bReceive, mySocket);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
this.tcp.Stop();
这是我从他们的开发者那里得到的原始代码。我尝试过各种async,TcpClient和不同套接字选项的组合,比如KeepAlive和DontLinger,但似乎都没有解决这个问题。
除了手动捕获C#中的数据包以获取正文外,是否有可用于读取整个请求的C#类?
答案 0 :(得分:2)
TCP是面向流的协议。每个人都知道,但很多开发人员在实现TCP接收器时都没有考虑到这一点。
当发送呼叫Send("ABCDEFG")
和客户呼叫Receive(buffer)
时,buffer
可能包含"ABCDEFG"
或"ABCD"
或"A"
或来自原始的任何子字符串以"A"
开头的数据。 TCP是一个数据流,没有任何有关消息边界的信息。
需要在编译期间接收长度未知的消息的接收方(如HTTP请求)必须包含一个接收标头,解析它的逻辑,然后等待直到收到完整的消息。
但是你不需要自己实现它。 C#具有已包含此逻辑的类HttpServer
。此外,还有支持REST的库。它正在重新发明轮子以实现REST服务器并从TcpListener
和套接字开始。
答案 1 :(得分:0)
我最终使用以下链接中的代码将服务器实现为异步。这样我就可以实现逻辑来重新读取流,如果尚未到达流的末尾。我只是因为我的情况而改变了文件结束条件。
以下是该文章的链接: