Socket Programming

    Date: 02/09/11 (C Sharp)    Keywords: asp, web, microsoft

    Hi,

    I have created a socket connection as described on MDSN web site:
    client: http://msdn.microsoft.com/en-us/library/bew39x2a(v=VS.85).aspx
    server: http://msdn.microsoft.com/en-us/library/fx6588te(v=VS.85).aspx

    It works fine. Events here are:
    1) Client sends request
    2) Server receives it
    3) Server sends response
    4) Server shutdown the socket
    5) Client receives response

    Then, I know, that between 2) an 3) might be a time gap. I want to send few interim responses like:
    2a) Server sends response: Still working on your request.
    The problem here is that I cannot send a response without shutting down the socket, but as I shout it down I am not able to send neither 3) nor another 2a)

    Is it possible for client to get response without closing the socket connection? Something like .flush()?


    corresponding piece of code:

    ...
       public class MathTask {
          public string inputData;
          public int MaxTryCount;
          public int DelayBetweenNotificationsSec;
          public bool complete = false;
          public MathTask(string _data, int _maxTry, int _delayBetweenNotifications) {
             inputData = _data;
             MaxTryCount = _maxTry;
             DelayBetweenNotificationsSec = _delayBetweenNotifications;
             complete = false;
          }
       }
    ...
    ...
          private static void Send(Socket handler, MathTask taskData)
          {
             // Convert the string data to byte data using ASCII encoding.
             byte[] byteData = Encoding.ASCII.GetBytes(taskData.inputData);
    
             if (taskData.complete || (taskData.MaxTryCount <= 0))
             { // final sending
                // Begin sending the data to the remote device.
                IAsyncResult res = handler.BeginSend(byteData, 0, byteData.Length, 0,
                    new AsyncCallback(SendCallback), handler);
    
             }
             else
             { // interim (notification) sending
                // Begin sending the data to the remote device.
                StateObject so = new StateObject();
                so.workSocket = handler;
                so.sb.Append(taskData.inputData);
                IAsyncResult res = handler.BeginSend(byteData, 0, byteData.Length, 0,
                    new AsyncCallback(SendInterimCallback), so);
             }
          }
    
          // after sending notification (task is running)
          private static void SendInterimCallback(IAsyncResult ar)
          {
             try
             {
                // Retrieve the socket from the state object.
                StateObject so = (StateObject)ar.AsyncState;
                int bytesSent = so.workSocket.EndSend(ar);
                
                Console.WriteLine("Sent {0} bytes to client.", bytesSent);
    
                // client receives response ONLY AFTER this statement
                so.workSocket.Shutdown(SocketShutdown.Both);
                so.workSocket.Close();
    
             }
             catch (Exception e)
             {
                Console.WriteLine(e.ToString());
             }
          }
    ...
    
    


    Thanks for response, the problem solved.

    That was not the server, but the client. Take a look at ReceiveCallback:
    private static void ReceiveCallback( IAsyncResult ar ) {
            try {
                // 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) {
                    // 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) {
                        response = state.sb.ToString();
                    }
                    // Signal that all bytes have been received.
                    receiveDone.Set();
                }
            } catch (Exception e) {
                Console.WriteLine(e.ToString());
            }
        }
    


    If client reads any bytesRead more than 0, it will store it in buffer and keep waiting for more data to come. Only when 0 bytes read it calls receiveDone.Set(); which finalize the receive process. Now I understand why it was working only after socket became closed.

    Source: http://csharp.livejournal.com/107817.html

« My open source project || Writing namespace to an XML... »


antivirus | apache | asp | blogging | browser | bugtracking | cms | crm | css | database | ebay | ecommerce | google | hosting | html | java | jsp | linux | microsoft | mysql | offshore | offshoring | oscommerce | php | postgresql | programming | rss | security | seo | shopping | software | spam | spyware | sql | technology | templates | tracker | virus | web | xml | yahoo | home