бредущий по жизни (svoysredychuzih) wrote in csharp,
бредущий по жизни
svoysredychuzih
csharp

Socket Programming

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.

Subscribe
  • Post a new comment

    Error

    default userpic
  • 5 comments