|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Problem with synchronous SocketI need to implement a socket server. I am using the following code to read from the socket. private int Read(ref byte[] buffer) { if (sapRequest.WaitForRequestBytes(socket) == 0) return 0; int numBytes = socket.Available; int numReceived = 0; buffer = new byte[numBytes]; if (numBytes > 0) { numReceived = socket.Receive(buffer, 0, numBytes, SocketFlags.None); } if (numReceived < numBytes) { byte[] tempBuffer = new byte[numReceived]; if (numReceived > 0) { Buffer.BlockCopy(buffer, 0, tempBuffer, 0, numReceived); } buffer = tempBuffer; } DWLog.Write(DWLogLevel.Information,"Number of bytes received: " + numReceived); return numReceived; } As you can see I am also using a method called WaitForRequestBytes. Here it is: public int WaitForRequestBytes(Socket socket) { int availBytes = 0; try { DWLog.Write(DWLogLevel.Information,"Socket.Available: " + socket.Available); if (socket.Available == 0) { // poll until there is data // DWLog.Write(DWLogLevel.Information, "Waiting for more data. Polling 100ms"); // socket.Poll(10000 /* 100ms */, SelectMode.SelectRead); DWLog.Write(DWLogLevel.Information, "Waiting for more data. Polling 100ms"); socket.Poll(10000 /* 100ms */, SelectMode.SelectRead); if (socket.Available == 0 && socket.Connected) { DWLog.Write(DWLogLevel.Information,"Waiting for more data. Polling 1s"); socket.Poll(100000 /* 1s */, SelectMode.SelectRead); // DWLog.Write(DWLogLevel.Information, "Waiting for more data. Polling 10sec"); // socket.Poll(10000000 /* 10sec */, SelectMode.SelectRead); } } availBytes = socket.Available; DWLog.Write(DWLogLevel.Information,"Bytes available: " + availBytes); } catch { } return availBytes; } My problem now is the following. The bytes don´t arrive continuously from the client. Therefore I introduced the method WaitForRequestBytes which polls for data. The polling does its job. The polling time is just enough to give the client enough time to send more data. Now this approach proves to be a drawback on performance since the polling is always executed even if there is no more data available from the client. For some reason and under certain circumstances socket.Available return 0 even when the client has not yet sent all its data. Can anyone explain thsi behaviour to me? Is there a reliable way to determine if all bytes where received from a client? I think asyncronous sockets are no solution for me, because I need control the order of the processing of the sockets. Thanks for your help. Hello, billa!
b> My problem now is the following. The bytes don´t arrive continuously b> from the client. Therefore I introduced the method WaitForRequestBytes b> which polls for data. Since you're using synchronous sockets it would be sufficient to call socket.Receive. This call will be blocking, that is when data will be available Receive will return it you in amount specified by passed buffer. No polling is needed. b> The polling does its job. The polling time is just enough to give the b> client enough time to send more data. Now this approach proves to be a b> drawback on performance since the polling is always executed even if b> there is no more data available from the client. b> For some reason and under certain circumstances socket.Available return b> 0 even when the client has not yet sent all its data. socket.Available == 0 means that there is no data that can be returned to you via Receive call. b> Is there a reliable way to determine if all bytes where received from a b> client? You cannot detect if client will sent all the data. The way how you can determine this either with the help of flags that are included in the data stream or with connection shutdown. b> I think asyncronous sockets are no solution for me, because I need b> control the order of the processing of the sockets. Do you receive data from different sockets? Hi Vadym,
I have tried socket.Receive but the problem there was that it waited for data until the client went in a timeout and that was definitely even longer than the polling took. To answer your question whether I am receiving data from differernt sockets. I am creating a new socket for each request coming in and handle that socket connection in a thread. I use the following code: public void Run() { try { Thread th = new Thread(new ThreadStart(StartListenThreaded)); th.Start(); } catch(System.Exception e) { } } The StartListenThreaded method looks like this: private void StartListenThreaded() { IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); IPEndPoint EndPoint = new IPEndPoint(IPAddress.Any, port); Socket ss = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ss.Bind( EndPoint); ss.Listen(20); try { while(true) { Socket sock = ss.Accept(); Connection con = new Connection(sock); Thread t = new Thread(new ThreadStart(con.ProcessOneRequest)); t.IsBackground=true; t.Priority=ThreadPriority.BelowNormal; t.Start(); } } catch (System.Exception e1) { } } I thought this was a good and performant way to handle the sockets. What do you think? What do you think about my statement from above about the socket.Receive problem? Thanks billa Hello, billa!
b> I have tried socket.Receive but the problem there was that it waited b> for data until the client went in a timeout and that was definitely b> even longer than the polling took. Hmm, thats strange, if there is no data then Poll also will return 0 for specific timout. The usage of Receive here can help you avoid polling for data. That is you'll receive data when it will be available. b> I thought this was a good and performant way to handle the sockets. b> What do you think? The scalability of such server can be poor, imagine when you will have great number of incomming connections/requests. take a look at ( http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/progthrepool.asp ) ( http://msdn.microsoft.com/msdnmag/issues/05/08/HighPerformanceSockets/default.aspx ) b> What do you think about my statement from above about the socket.Receive b> problem? It depends, however in your case I think that it is better to block on Receive than Poll. Hi again Vadym,
I guess I will try the thing with Receive. The problem with it is that my client does not close the socket. This means that Receive will wait for data a long time until the client times out. How can I handle this problem . Do you also have a solution for this? Thanks billa Hello, billa!
b> I guess I will try the thing with Receive. The problem with it is that b> my client does not close the socket. This means that Receive will wait b> for data a long time until the client times out. How can I handle this b> problem . Use flags that will indicate the end if client message b> Do you also have a solution for this? Do you communicate with client using application ( your custom ) protocol? Generally connection close is not required, however in this case the data passed to and from client is organized according to definite communication protocol. Client & server know the protocol and can communicate using it without closing connection and blockin. For instance, mail and news applications.... Hi Vadym,
That is another problem. I have no control on what the client sends. Basically it sends HTTP requests. So I can not send any stop flags or anything like that. Can I set a timeout on the socket before I use the Receive method? The socket Receive would then automatically timeout when no further data is send by the client after a certain time. It something like that possible? Thanks billa. Hello, billa!
Take a look at SocketOptionName.ReceiveTimeout. |
|||||||||||||||||||||||