C# TCP客户端发送但不接收消息
C# TCP client sending but not receiving messages
我继承了一些 TCP 客户端的代码。它发送一条消息,然后在完成时等待确认消息。目前它发送消息,但是当它等待回复消息时它永远不会收到它。 SendMessage()
方法是外部调用的方法。
我设置了断点,可以看到它命中了 Receive()
方法,但从未命中 ReceiveCallback()
任何朝着正确方向的帮助或推动都将不胜感激。
public class SocketService
{
private ManualResetEvent connectDone = new ManualResetEvent(false);
private ManualResetEvent sendDone = new ManualResetEvent(false);
private ManualResetEvent receiveDone = new ManualResetEvent(false);
string ipAddress;
private int portNum;
string returnMessage;
// private string hostName = Dns.GetHostName ();
public SocketService(string ipAddress, int portNum)
{
this.ipAddress = ipAddress;
this.portNum = portNum;
}
public event Logging OnLogging;
private void WriteLogMessage(string message)
{
if (this.OnLogging != null)
this.OnLogging(message);
}
//char endOfLineSeparator = (char) 0x1C;
//char cr = (char) 0x0D;
//char vt = (char) 0x0B;
public string SendMessage(string message)
{
IPAddress ip = IPAddress.Parse(this.ipAddress);
IPEndPoint remoteEP = new IPEndPoint(ip, portNum);
connectDone.Reset();
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback),
client);
connectDone.WaitOne();
//sendDone.Reset();
WriteLogMessage("send message");
Send(client, message);
sendDone.WaitOne();
//receiveDone.Reset();
WriteLogMessage("receive message");
Receive(client);
receiveDone.WaitOne();
client.Shutdown(SocketShutdown.Both);
client.Close();
return this.returnMessage;
}
private void Send(Socket client, String data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
client.BeginSend(byteData,
0,
byteData.Length,
0,
new AsyncCallback(SendCallback),
client);
}
private void SendCallback(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
sendDone.Set();
}
private void ConnectCallback(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
connectDone.Set();
}
private void Receive(Socket client)
{
StateObject state = new StateObject(client);
client.BeginReceive(state.Buffer,
0,
StateObject.BufferSize,
0,
new AsyncCallback(ReceiveCallback),
state);
}
private void ReceiveCallback(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.WorkSocket;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
state.StoredContent.Append(Encoding.ASCII.GetString(state.Buffer, 0, bytesRead));
client.BeginReceive(state.Buffer,
0,
StateObject.BufferSize,
0,
new AsyncCallback(ReceiveCallback),
state);
WriteLogMessage(state.StoredContent.ToString());
}
else
{
this.returnMessage = state.StoredContent.ToString();
receiveDone.Set();
}
}
}
您的 SendMessage
和 Receive
函数实际上没有任何作用。他们只是发送和接收字节。他们没有 "message" 的概念,在发送消息时不标记消息的结尾,在接收消息时也不识别消息的结尾。简而言之,您忘记实现网络协议并假设 TCP 是一种消息服务,而实际上它是一种字节流服务。
如果你需要发送和接收消息,你必须精确定义什么是"message"并编写代码来发送和接收它们。它不会变魔术。
正如 David Schwartz 所指出的,您需要一种分隔消息的方法。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
到头来是无人知晓的事情。这些是 HL7 消息,消息末尾缺少一个隐藏字符。接收方一直在等待消息发送完成,但是没有这个字符就没有看到完整的消息,因此也没有发回确认。
我继承了一些 TCP 客户端的代码。它发送一条消息,然后在完成时等待确认消息。目前它发送消息,但是当它等待回复消息时它永远不会收到它。 SendMessage()
方法是外部调用的方法。
我设置了断点,可以看到它命中了 Receive()
方法,但从未命中 ReceiveCallback()
任何朝着正确方向的帮助或推动都将不胜感激。
public class SocketService
{
private ManualResetEvent connectDone = new ManualResetEvent(false);
private ManualResetEvent sendDone = new ManualResetEvent(false);
private ManualResetEvent receiveDone = new ManualResetEvent(false);
string ipAddress;
private int portNum;
string returnMessage;
// private string hostName = Dns.GetHostName ();
public SocketService(string ipAddress, int portNum)
{
this.ipAddress = ipAddress;
this.portNum = portNum;
}
public event Logging OnLogging;
private void WriteLogMessage(string message)
{
if (this.OnLogging != null)
this.OnLogging(message);
}
//char endOfLineSeparator = (char) 0x1C;
//char cr = (char) 0x0D;
//char vt = (char) 0x0B;
public string SendMessage(string message)
{
IPAddress ip = IPAddress.Parse(this.ipAddress);
IPEndPoint remoteEP = new IPEndPoint(ip, portNum);
connectDone.Reset();
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback),
client);
connectDone.WaitOne();
//sendDone.Reset();
WriteLogMessage("send message");
Send(client, message);
sendDone.WaitOne();
//receiveDone.Reset();
WriteLogMessage("receive message");
Receive(client);
receiveDone.WaitOne();
client.Shutdown(SocketShutdown.Both);
client.Close();
return this.returnMessage;
}
private void Send(Socket client, String data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
client.BeginSend(byteData,
0,
byteData.Length,
0,
new AsyncCallback(SendCallback),
client);
}
private void SendCallback(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
sendDone.Set();
}
private void ConnectCallback(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
connectDone.Set();
}
private void Receive(Socket client)
{
StateObject state = new StateObject(client);
client.BeginReceive(state.Buffer,
0,
StateObject.BufferSize,
0,
new AsyncCallback(ReceiveCallback),
state);
}
private void ReceiveCallback(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.WorkSocket;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
state.StoredContent.Append(Encoding.ASCII.GetString(state.Buffer, 0, bytesRead));
client.BeginReceive(state.Buffer,
0,
StateObject.BufferSize,
0,
new AsyncCallback(ReceiveCallback),
state);
WriteLogMessage(state.StoredContent.ToString());
}
else
{
this.returnMessage = state.StoredContent.ToString();
receiveDone.Set();
}
}
}
您的 SendMessage
和 Receive
函数实际上没有任何作用。他们只是发送和接收字节。他们没有 "message" 的概念,在发送消息时不标记消息的结尾,在接收消息时也不识别消息的结尾。简而言之,您忘记实现网络协议并假设 TCP 是一种消息服务,而实际上它是一种字节流服务。
如果你需要发送和接收消息,你必须精确定义什么是"message"并编写代码来发送和接收它们。它不会变魔术。
正如 David Schwartz 所指出的,您需要一种分隔消息的方法。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
到头来是无人知晓的事情。这些是 HL7 消息,消息末尾缺少一个隐藏字符。接收方一直在等待消息发送完成,但是没有这个字符就没有看到完整的消息,因此也没有发回确认。