socket receive question

Hi,

I need to build a client-server tcp socket program, the client needs to send some commands to the server and needs to wait there for the response from the server. I am thinking of using sendto&receivefrom to do this synchronized call.

But the server side will send some data to client irregularly, so I need to have something listerning, I think I must use BeginReceive to receive the data from this socket.

So the problem is how to mix synchronize and asynchronize during receiving. I am a socket newbie and am confused with this case. Would you please to clarify it to me and give me some hints how to implement it Thanks a lot.



Answer this question

socket receive question

  • Llorean

    Thanks, Frank & Rizwan,

    After reading your posts, I got some ideas about socket. Actually I read a lot of articles about socket programming recently, I am confused with "BeginReceive", "EndReceve" and "WaitHandler", do you have some good links that could clarify these concepts

    I saw a lot of samples that in callback function of beginreceive, immediatelly call endreceive method, so in this case, how many bytes would be in the receive buffer

    cb.S.BeginReceive(Packet.Data, 0, Packet.Data.Length, SocketFlags.None, CallBackHandler, Packet);

    private void OnDataReceived(IAsyncResult Asyn) {
    SocketPacket Packet = (SocketPacket)Asyn.AsyncState;

    if (!Packet.thisSocket.Connected) return;

    int CollectedDataLength = Packet.thisSocket.EndReceive(Asyn);

    ...

    WaitForData(); //start polling again

    }

    let's say the server will send 40 bytes as the response1, then 50 bytes as the response2, and 100 bytes for the data. what would be the CollectedDataLength

    Thanks again.

    Best Regards,

    Edward


  • StUdEnT in distress

    edward1028 wrote:
    "BeginReceive", "EndReceve" and "WaitHandler", do you have some good links that could clarify these concepts

    I don't sorry. I'm sure there are some out there, I just haven't come across them. These SDK articles discuss using asynchronous sockets from the client and server end and provide complete client and server programs

    http://windowssdk.msdn.microsoft.com/en-us/library/bbx2eya8.aspx

    http://windowssdk.msdn.microsoft.com/en-us/library/5w7b7x5f.aspx

    http://windowssdk.msdn.microsoft.com/en-us/library/bew39x2a.aspx

    http://windowssdk.msdn.microsoft.com/en-us/library/fx6588te.aspx

    One thing to watch out for in sockets programming is that what you get from the socket is a sequence of bytes. You are responsible for assembling those sequences into a useful message and usually you need to embed some data within the message to help figure out where one message ends and another message starts. For example, in the Server sample above, the handler looks for "<EOF>" within the received string to find the end of the message being received. The client on the other hand relies on the fact that the server shuts the connection down (by calling Close)

    The samples are rather artificial, in real life there would typically be more messages. One common trick is to send a message length as the first few bytes. So, the receiver reads (say) 4 bytes to start with and then reads however many bytes are specified by the bit pattern read so far. Other techniques use markers like the "<EOF>" above or use fixed length messages or use a state machine to analyze the bytes coming in as they arrive .

    I saw a lot of samples that in callback function of beginreceive, immediatelly call endreceive method, so in this case, how many bytes would be in the receive buffer

    This is one of the trickier aspects of sockets programming. The short answer is "you don't know". The EndReceive documentation says this "the EndReceive method will read as much data as is available up to the number of bytes you specified in the size parameter of the BeginReceive method." But that begs the question what does "available" mean

    let's say the server will send 40 bytes as the response1, then 50 bytes as the response2, and 100 bytes for the data. what would be the CollectedDataLength

    The problem is that what the server did is, in some sense, irrelevant. As those messages are transmitted across the network, intermediate nodes like routers are allowed to combine these bytes into fewer chunks or to fragment them into more chunks or all of the above. You might get all 190 bytes in one EndReceive call or you might require 190 separate EndReceive calls to get each byte separately. Or anything in between. The first EndReceive might get 47 bytes, the second might get 10, the third might get 60 and the fourth get whatever's left. You just don't know.

    That's why the client and server samples above receive whatever they receive and assemble the various bytes received into the StringBuilder. That way, no matter how many (or how few) bytes a single EndReceive delivers, eventually the program receives them all and then processes the message received.


  • Shivapc

    I don't get any response from the server, and I know the server is working. What is wrong This is the code I'm using.

    Socket client = null;

    private static ManualResetEvent connectDone = new ManualResetEvent(false);

    private static ManualResetEvent sendDone = new ManualResetEvent(false);

    private void PostMessage(byte[] bye)

    {

    string message = "";

    ASCIIEncoding enc = new ASCIIEncoding();

    message = enc.GetString(bye);

    MessagesField.Text += message;

    }

    private void Send(string message)

    {

    byte[] byteData = Encoding.ASCII.GetBytes(message);

    client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);

    }

    private void SendCallback(IAsyncResult ar)

    {

    // Retrieve the socket from the state object.

    Socket client = (Socket)ar.AsyncState;

    // Complete sending the data to the remote device.

    int bytesSent = client.EndSend(ar);

    sendDone.Set();

    }

    private void Receive()

    {

    updater.Enabled = false;

    StateObject state = new StateObject();

    state.workSocket = client;

    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);

    }

    private void ReceiveCallback(IAsyncResult ar)

    {

    updater.Enabled = true;

    MessageBox.Show("motar");

    // Retrieve the state object and the client socket

    // from the asynchronous state object.

    StateObject state = (StateObject)ar.AsyncState;

    Socket client = state.workSocket;

    // Read data from the remote device.

    int bytesRead = client.EndReceive(ar);

    if (bytesRead > 0 && false)

    {

    // There might be more data, so store the data received so far.

    state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

    // Get the rest of the data.

    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);

    }

    else

    {

    // All the data has arrived; put it in response.

    if (state.sb.Length > 1)

    {

    MessageBox.Show(state.sb.ToString());

    }

    }

    }

    private void ConnectCallback(IAsyncResult ar)

    {

    try

    {

    // Retrieve the socket from the state object.

    Socket client = (Socket)ar.AsyncState;

    // Complete the connection.

    client.EndConnect(ar);

    // Signal that the connection has been made.

    connectDone.Set();

    }

    catch (Exception e)

    {

    MessageBox.Show(e.ToString());

    }

    }

    public Form1()

    {

    InitializeComponent();

    }

    private void Form1_Load(object sender, EventArgs e)

    {

    IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234);

    client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    client.BeginConnect(endPoint, new AsyncCallback(ConnectCallback), client);

    connectDone.WaitOne();

    Receive();

    }



  • bahaa_sa5

    edward1028 wrote:
    I need to build a client-server tcp socket program

    Are you sure you want to take that low level approach Sometimes using a socket is the only way to achieve your goal but it does require that you write a lot of code to handle the socket itself, deal with fragmented packets, etc. For client-server interractions, the Web Services model can relieve a lot of that burden and let you focus on the code you really care about. There are a number of Web services 'walkthroughs' that can help you write your first simple web service to get some idea of how it all works: http://msdn2.microsoft.com/en-us/library/cbsxhx87.aspx

    , the client needs to send some commands to the server and needs to wait there for the response from the server. I am thinking of using sendto&receivefrom to do this synchronized call.

    But the server side will send some data to client irregularly, so I need to have something listerning, I think I must use BeginReceive to receive the data from this socket.

    If you run your request-response data and your asynchronous data through the same socket you're going to give yourself quite a headache. For instance, let's say your client sends a request to the server. Just as the bytes leave the client system the server decides to send some asynchronous data. The request and the asynchronous data pass each other in transit. The client is now looking for a response to the request it sent but what arrives is the asynchronous data the server sent.

    So the problem is how to mix synchronize and asynchronize during receiving.
    You can't really mix things that way. You need to have one thing processing all received data in a consistent way. That one thing can be an asynchronous callback dealing with the event fired by BeginReceive or it can be a separate thread repeatedly calling Receive and processing the results of that receive call but either way it is going to have to handle everything - responses to client requests and spontaneously occurring data sent by the server.

    Alternatively, you could use two separate sockets, one for request/response data and a second one for the spontaneous server data.


  • Osmose1000

    Whatever you are using for Socket TCP/IP Communication Socket or their Wrappers TcpClient and TcpListener try to use NetworkStream to send and read data because it's simple to use for a newbie that usinf Socket.BeginSend etc....

    To combine both Syncrnonous and Asynchrnonous Methods,

    First Do and Asyncrhnous read of Network Stream when it reads some data and reached in its callback then read data Synchronously. It'll not block the execution because it was already in a seperate thread managed by System's Thread Pool due to first Asynchrnous call:

    The best this is to do Read 4 bytes for example using begin read, now after 4 bytes read control is transfered to call back function now read next bytes synchonously and so on!

    I hope this will Help!

    Best Regards,



  • socket receive question