Search code examples
c#socketstcpservernetworkstream

How to make a server reply after receiving a request/data


I'm trying to set up a connection between a client program and a server program. Sending data from the client to the server works fine, but I have no clue how I can send back a reply immediately from the server to the client. For example in this case I have a program for a hotel to store all reservations (server) and a clientprogram for where people can look up their reservations. The clientprogram sends the ID of the client to the server and needs to send a serialized Hashtable of that client's reservations back.

My client code looks like this:

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

const int POORT = 4001;
IPAddress ipaddress = IPAddress.Parse("127.0.0.1");

socket.Connect(new IPEndPoint(ipaddress, POORT));

using (NetworkStream ns = new NetworkStream(socket)) {
     using (StreamWriter sw = new StreamWriter(ns)) {
           sw.WriteLine(klantId);
           sw.Flush();                 
     }
}

socket.Shutdown(SocketShutdown.Both);
socket.Close();

My server code:

IPAddress ipaddress = IPAddress.Parse("127.0.0.1");
IPEndPoint ep = new IPEndPoint(ipaddress, 4001);

Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,                               ProtocolType.Tcp);
serverSocket.Bind(ep);
serverSocket.Listen(50);

try {
     string klantid;
     while (true) {
          using (Socket clientSocket = serverSocket.Accept()) {
              using (NetworkStream ns = new NetworkStream(clientSocket)) {
                  using (StreamReader sr = new StreamReader(ns)) {
                      klantid = sr.ReadLine();

                      // Searches the reservations
                      Hashtable reservaties = hotel.ReservatiesZoeken(int.Parse(klantid));

                      // Tried this to send the data. Doesn't seem to work.
                      using (MemoryStream stream = new MemoryStream()) {
                          BinaryFormatter formatter = new BinaryFormatter();
                             formatter.Serialize(stream, reservaties);
                             stream.Flush();
                          }
                      }
                  }
               }
          }
    }
    finally {
         serverSocket.Shutdown(SocketShutdown.Both);
         serverSocket.Close();
    } 

I guess I could implement a listener in the client and make a new connection from the server to the client, but I couldn't help but feeling that it should be possible to send the reply over the same connection as the request.


Solution

  • You are closing the socket on the client right after you sent the ID. You need to keep it open and wait for the server to send it's data, e.g.:

    Socket socket = new Socket(AddressFamily.InterNetwork, ...);
    
    // open and send ID
    
    int dataAvailable = 0;
    while (dataAvailable == 0 || dataAvailable != socket.Available)
    {
        dataAvailable = socket.Available;
        Thread.Sleep(100); // if no new data after 100ms assume transmission finished
    }
    
    var data = new byte[dataAvailable];
    socket.Receive(data);
    
    socket.Shutdown(SocketShutdown.Both);
    socket.Close();
    

    DISCLAIMER: This is not "production ready code" and should just give you a hint how you could solve your problem. Espceially the "wait 100ms" part should NOT be used in production code...