简体   繁体   中英

C# sockets: can't read after writing to socket

In my client/server application my client wiil communicate with the server for 2 functions: the client will either request data from the server or it will send data so the server will save it. I'm using one socket for both methods, and the method to be used is defined by the first byte sent. If the first byte is "1" it is requesting data. If it is "2", it will send data (data bytes are sent after the "2" byte). It works perfectly for sending data. But when I'm requesting data it works, as long as I don't read the socket stream in the client. It's like if I make the client read data after sending data, the server will have no data to read, and it just crashes when trying to read the data.

Here is my server code:

private const int BufferSize = 1024;
NetworkStream netstream = null;
byte[] RecData = new byte[BufferSize];
int RecBytes;

try {
     netstream = clientSocket.GetStream();
     int totalrecbytes = 0;

     using (MemoryStream ms = new MemoryStream()) {
         //When I get here, there is no data to read
         while ((RecBytes = netstream.Read(RecData, 0, RecData.Length)) > 0) {
             ms.Write(RecData, 0, RecBytes);
             totalrecbytes += RecBytes;
         }

         byte[] bytes = ms.ToArray();
         byte b = bytes[0];

         switch (b) {
             case 1:

             //Here I gather data and put it in "stream" variable


             byte[] SendingBuffer = null;
             int NoOfPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(stream.Length) / Convert.ToDouble(BufferSize)));
             int TotalLength = (int)stream.Length, CurrentPacketLength, counter = 0;
             for (int i = 0; i < NoOfPackets; i++) {
                 if (TotalLength > BufferSize) {
                     CurrentPacketLength = BufferSize;
                     TotalLength = TotalLength - CurrentPacketLength;
                 }
                 else
                     CurrentPacketLength = TotalLength;
                 SendingBuffer = new byte[CurrentPacketLength];
                 stream.Read(SendingBuffer, 0, CurrentPacketLength);
                 netstream.Write(SendingBuffer, 0, (int)SendingBuffer.Length);
             }
             netstream.Flush();


         }
         catch (Exception e) {
             Console.WriteLine("EXCEPTION:\n" + e.ToString());
         }

         break;
     case 2:              
         //Code to read data

         break;
     }
 }
 netstream.Close()
 clientSocket.Close();

And here is my client code:

using (System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient()) {

    string returnData = "";

    IAsyncResult ar = clientSocket.BeginConnect("127.0.0.1", 8080, null, null);
    System.Threading.WaitHandle wh = ar.AsyncWaitHandle;
    try {
        if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5), false)) {
            clientSocket.Close();
            Console.WriteLine("Timeout");
            return;
        }

        System.Net.Sockets.NetworkStream serverStream = clientSocket.GetStream();

        byte b = 1;

        byte[] outStream = { b };
        serverStream.Write(outStream, 0, outStream.Length);
        serverStream.Flush();

        //If I comment following lines, the server can read sent data, but server can't otherwise
        byte[] RecData = new byte[1024];
        int RecBytes;
        int totalrecbytes = 0;
        MemoryStream MS = new MemoryStream();
        while ((RecBytes = serverStream.Read(RecData, 0, RecData.Length)) > 0) {
            MS.Write(RecData, 0, RecBytes);
            totalrecbytes += RecBytes;
        }
        serverStream.Close();
        clientSocket.Close();
        clientSocket.EndConnect(ar);

    }
    catch (Exception ex) {
        Console.WriteLine("Exceção: " + ex.ToString());
    }
    finally {
        wh.Close();
    }
}

So, how can I send data to server and read the response? (I tried even putting the thread to sleep after sending data, with no luck.) Thanks in advance.

EDIT: With some debug messages I discovered that the server do read the "1" byte that was sent, but somehow it gets stuck inside the while loop, like, the server just stops there, no more loops and it does not leave the while loop. I saw that after writing "loop" in console inside the while loop, and writing read bytes also in console. It wrote "loop" once, and the read byte.

This code worries me:

     //When I get here, there is no data to read
     while ((RecBytes = netstream.Read(RecData, 0, RecData.Length)) > 0) {
         ms.Write(RecData, 0, RecBytes);
         totalrecbytes += RecBytes;
     }

You are reading until the client closes the connection (or shuts down sending, which you don't do). But the client only closes when the server has replied. The server reply will never come. It is a deadlock.

Solution: Read a single byte to determine the requests command ( b ).

Unrelated to the question, your "packetised" sending ( NoOfPackets , ...) does not seem to serve any purpose. Just use Stream.Copy to write. TCP does not have packets.

An even better solution would be to abandon your custom TCP protocol and use an HTTP library. All these concerns just go away. There are various smaller problems with your code that are very typical to see in TCP code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM