多个客户端连接到服务器的 C# 套接字读取缓冲区错误
C# socket read buffer error with multiple clients connecting to servers
我编写了一个 Windows C# 应用程序,它最多可以创建 16 个线程。每个线程为远程设备创建一个套接字。每个线程发送命令来读取设备状态。 (每 300 毫秒)当我创建一个或两个线程来读取状态时就可以了。但是当我创建 10 个线程来读取设备状态时,我会在套接字接收缓冲区中得到错误的数据。
我的socket驱动代码请参考以下:
class SocketClient {
private IPAddress ipAddress;
private IPEndPoint remoteEP;
private Socket mSocket;
private SocketAsyncEventArgs e = new SocketAsyncEventArgs();
private System.Timers.Timer timer_connection;
private static byte[] response = new byte[1024];
private Boolean waittingConnectDone;
private Boolean boolConnected;
public SocketClient() {
}
private byte[] acknowledge = null;
public Boolean Connect(String IP, int Port) {
Boolean bRet = true;
ipAddress = IPAddress.Parse(IP);
remoteEP = new IPEndPoint(ipAddress, Port);
mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//mSocket.ReceiveTimeout = GlobalVar.ethernet_timeout;
mSocket.ReceiveTimeout = 500;
try {
waittingConnectDone = false;
e.RemoteEndPoint = remoteEP;
e.UserToken = mSocket;
e.Completed += new EventHandler<SocketAsyncEventArgs>(e_Completed);
mSocket.ConnectAsync(e);
if (timer_connection != null) {
timer_connection.Dispose();
} else {
timer_connection = new System.Timers.Timer();
}
timer_connection.Interval = 2000;
timer_connection.Elapsed += new ElapsedEventHandler(timer_connection_Tick);
timer_connection.Start();
while (true) {
if (waittingConnectDone)
break;
Application.DoEvents();
}
bRet = boolConnected;
//sender.Connect(remoteEP);
} catch {
Debug.WriteLine("### Ethernet ### Connection Error!");
bRet = false;
}
return bRet;
}
private void e_Completed(object sender, SocketAsyncEventArgs e) {
boolConnected = true;
waittingConnectDone = true;
}
private void timer_connection_Tick(object sender, EventArgs e) {
if (!mSocket.Connected) {
timer_connection.Stop();
boolConnected = false;
waittingConnectDone = true;
}
}
public void Disconnect() {
try {
mSocket.Shutdown(SocketShutdown.Both);
mSocket.Close();
} catch {
}
}
每个线程使用以下代码读取设备状态:
private byte[] acknowledge = null;
private static byte[] response = new byte[1024];
public byte[] sendCommand(byte[] Cmp_TxData) {
try {
bytesSent = mSocket.Send(Cmp_TxData);
bytesRec = mSocket.Receive(response);
acknowledge = new byte[bytesRec];
Array.Copy(response, 0, acknowledge, 0, bytesRec);
}
catch
{
acknowledge = null;
}
return acknowledge;
}
缓冲区数据错误如下:
TX --> 00-03-01-F4-00-03-44-14
RX <-- 00-00-00-00-00-00-00-00-00-00-00
有时读到正确的数据,有时读到的数据全是0!
我的套接字驱动有问题吗?
非常感谢您的帮助!!
我没有检查所有发布的代码(我怀疑可能有更多的错误,如果你自己尝试多线程很难),但是这一行:
private static byte[] response = new byte[1024];
绝对是您报告的错误类型的来源。此行声明了一个在所有线程之间共享的缓冲区。
因此,如果多个线程执行此操作:
bytesRec = mSocket.Receive(response);
此响应缓冲区中的数据可以并发修改。
要解决此特定错误,您可以确保使用 [ThreadStatic]
或 ThreadLocal
为每个线程创建一个静态缓冲区(参见示例 http://reedcopsey.com/2009/11/12/thread-specific-data-becomes-easier-in-net-4-0-via-threadlocalt/)。
我编写了一个 Windows C# 应用程序,它最多可以创建 16 个线程。每个线程为远程设备创建一个套接字。每个线程发送命令来读取设备状态。 (每 300 毫秒)当我创建一个或两个线程来读取状态时就可以了。但是当我创建 10 个线程来读取设备状态时,我会在套接字接收缓冲区中得到错误的数据。
我的socket驱动代码请参考以下:
class SocketClient {
private IPAddress ipAddress;
private IPEndPoint remoteEP;
private Socket mSocket;
private SocketAsyncEventArgs e = new SocketAsyncEventArgs();
private System.Timers.Timer timer_connection;
private static byte[] response = new byte[1024];
private Boolean waittingConnectDone;
private Boolean boolConnected;
public SocketClient() {
}
private byte[] acknowledge = null;
public Boolean Connect(String IP, int Port) {
Boolean bRet = true;
ipAddress = IPAddress.Parse(IP);
remoteEP = new IPEndPoint(ipAddress, Port);
mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//mSocket.ReceiveTimeout = GlobalVar.ethernet_timeout;
mSocket.ReceiveTimeout = 500;
try {
waittingConnectDone = false;
e.RemoteEndPoint = remoteEP;
e.UserToken = mSocket;
e.Completed += new EventHandler<SocketAsyncEventArgs>(e_Completed);
mSocket.ConnectAsync(e);
if (timer_connection != null) {
timer_connection.Dispose();
} else {
timer_connection = new System.Timers.Timer();
}
timer_connection.Interval = 2000;
timer_connection.Elapsed += new ElapsedEventHandler(timer_connection_Tick);
timer_connection.Start();
while (true) {
if (waittingConnectDone)
break;
Application.DoEvents();
}
bRet = boolConnected;
//sender.Connect(remoteEP);
} catch {
Debug.WriteLine("### Ethernet ### Connection Error!");
bRet = false;
}
return bRet;
}
private void e_Completed(object sender, SocketAsyncEventArgs e) {
boolConnected = true;
waittingConnectDone = true;
}
private void timer_connection_Tick(object sender, EventArgs e) {
if (!mSocket.Connected) {
timer_connection.Stop();
boolConnected = false;
waittingConnectDone = true;
}
}
public void Disconnect() {
try {
mSocket.Shutdown(SocketShutdown.Both);
mSocket.Close();
} catch {
}
}
每个线程使用以下代码读取设备状态:
private byte[] acknowledge = null;
private static byte[] response = new byte[1024];
public byte[] sendCommand(byte[] Cmp_TxData) {
try {
bytesSent = mSocket.Send(Cmp_TxData);
bytesRec = mSocket.Receive(response);
acknowledge = new byte[bytesRec];
Array.Copy(response, 0, acknowledge, 0, bytesRec);
}
catch
{
acknowledge = null;
}
return acknowledge;
}
缓冲区数据错误如下:
TX --> 00-03-01-F4-00-03-44-14
RX <-- 00-00-00-00-00-00-00-00-00-00-00
有时读到正确的数据,有时读到的数据全是0!
我的套接字驱动有问题吗?
非常感谢您的帮助!!
我没有检查所有发布的代码(我怀疑可能有更多的错误,如果你自己尝试多线程很难),但是这一行:
private static byte[] response = new byte[1024];
绝对是您报告的错误类型的来源。此行声明了一个在所有线程之间共享的缓冲区。
因此,如果多个线程执行此操作:
bytesRec = mSocket.Receive(response);
此响应缓冲区中的数据可以并发修改。
要解决此特定错误,您可以确保使用 [ThreadStatic]
或 ThreadLocal
为每个线程创建一个静态缓冲区(参见示例 http://reedcopsey.com/2009/11/12/thread-specific-data-becomes-easier-in-net-4-0-via-threadlocalt/)。