Click here to Skip to main content
15,889,843 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I write an Windows C# application which can create up to 16 threads. Each thread creates a socket for a remote device. Each thread send commands to read the device status. (every 300 ms) It is OK when I create one or two threads to read the status. But when I create 10 threads to read device status, I will get wrong data in the socket receive buffer.

Please refer to the following for my socket driver code:

C#
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 {
        }
    }


Each Thread use following code to read the device status:

C#
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;
}

And the buffer data error is something like following:
TX --> 00-03-01-F4-00-03-44-14 
RX <-- 00-00-00-00-00-00-00-00-00-00-00


Sometimes I read correct data, but sometimes the data are all 0!

Is there anything wrong with my socket driver?

Really appreciate your help.
Posted
Updated 23-Feb-15 18:46pm
v2
Comments
StM0n 24-Feb-15 0:51am    
I'm not quite sure, but <<private static byte[] response = new byte[1024];>> shouldn't be private... is there a reason therefore?
Yu-Long Fang 24-Feb-15 3:55am    
I set it to public, but still with error. Thank you for your information anyway.

1 solution

C#
private static byte[] response = new byte[1024];

That means only one buffer for all threads. The buffer should be created locally within the thread, not as a static entity. You also call Receive straight after Send, but you do not check whether you received any data, or whether there is still some data being transmitted, see https://msdn.microsoft.com/en-us/library/8s4y8aff(v=vs.110).aspx[^].
 
Share this answer
 
Comments
Yu-Long Fang 24-Feb-15 5:53am    
I modify code as following, but still with the same error!

bool goOn = true;
int recvd = 0;
byte[] temp_buf = new byte[1024];
int expected_read_len = ethernet_get_read_len(Cmp_TxData);

try {
bytesSent = mSocket.Send(Cmp_TxData);
}
catch {
return null;
}

while (goOn)
{
try
{
recvd = mSocket.Receive(response);
}
catch
{
//something bad happened (timeout, connection reset, etc). Deal with it
return null;
}

if (recvd > 0)
{
// do something with the bytes, e. g. pass them on to a List<byte> etc.
Array.Copy(response, 0, temp_buf, bytesRec, recvd);
bytesRec = bytesRec + recvd;

if (expected_read_len != 0) {
if (bytesRec == expected_read_len)
{
goOn = false;
// other side closed, do something useful with data received
acknowledge = new byte[bytesRec];
Array.Copy(response, 0, acknowledge, 0, bytesRec);
}
}
}
else
{
// other side closed, do something useful with data received
// It's the way that sockets work. 0 can only be received if the socket is down.
goOn = false;
acknowledge = new byte[bytesRec];
Array.Copy(response, 0, acknowledge, 0, bytesRec);
}
}
Richard MacCutchan 24-Feb-15 6:45am    
Nothing obvious shows up, so I can only suggest adding some debug code to try and trace what is happening at each stage.
Yu-Long Fang 24-Feb-15 7:38am    
I set the buffer as local not static and it works! Thank you!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900