Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Socket programming- client server principles

Tags:

c#

tcpclient

I'm embarrassed to even ask this question, but after an exhausting search in google (starting to have MSDN...), I've decided to post it:

Just now started learning client-server programming (using C#), and trying to write my first code using tcpClient. I'm writing both the server side and the client side. here's my question: Constantly, the client sends one String to the server, and then the server sends a String back to the client and so forth. Can't the server send 2 Strings in a row? he has to wait for the client response? is this the principle of client-server??

Once again, sorry for the lousy question. Thanks...

<> I'll try to post some of my code (a long one...). I tryed to cut the redandent parts, so hope the code makes any sense... (i marked the main problam with //*********)

public class MServer2
{
Dictionary<String, String> nameAndPass = new Dictionary<String, String>();
Dictionary<String, List<String> > nameAndMail = new Dictionary<String, List<String>>();

public static void Main()
{
    new MServer2();
}

public MServer2()
{
    TcpListener server = new TcpListener(8500);
    try
    {
        server.Start();
        Console.WriteLine("started " + server);
        while (true)
        {
            TcpClient client = server.AcceptTcpClient();
            Console.WriteLine("connection accepted " + client);
            new Server1(client, nameAndPass, nameAndMail);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("exception" + e);
    }
    finally
    {
        server.Stop();
    }
}

class Server1
{
TcpClient client;
NetworkStream netStream;
Dictionary<String, String> nameAndPass1 = new Dictionary<String, String>();
Dictionary<String, List<String>> nameAndMail1 = new Dictionary<String, List<String>>();

internal Server1(TcpClient client, Dictionary<String, String> nameandPassFromFile, Dictionary<String, List<String> > nameAndMailsFromFile)
{
    nameAndPass1 = nameandPassFromFile;
    nameAndMail1 = nameAndMailsFromFile;

    this.client = client;
    Thread thr = new Thread(new ThreadStart(Run));
    thr.Start();
}

public void Run()
{
    try
    {
        netStream = client.GetStream();
        StreamReader reader = new StreamReader(netStream);
        StreamWriter writer = new StreamWriter(netStream);
        writer.AutoFlush = true;
        Console.WriteLine("beginning to receive loop");

        writer.WriteLine("Choose your user name.");
        strFromClient = reader.ReadLine();
        userName = strFromClient;

        writer.WriteLine("Choose your user password.");
        strFromClient = reader.ReadLine();

        password = strFromClient;

        writer.WriteLine("Do you want to see the list of email addresses? (y/n)");
        strFromClient = reader.ReadLine();

//***********************************************************************************
//HERE'S MY PROBLAM:
//HERE THE CLIENT WILL GET A STRING SHOWING HIS EMAILS, AND I WANT HIM TO GET ANOTHER     STRING ASKING "Do you want to add an email address? (y/n)", BUT IT LOOKS LIKE THE SERVER     "WAITS" FOR A RESPONSE FROM THE CLIENT TO SHOW THE NEXT STRING...
        if (strFromClient == "y")
        {   
            String tmpStr = null;
            List<String> tmp = nameAndMail1[userName];
            for(int i=0; i<nameAndMail1[userName].Count; i++)
            {
                tmpStr += tmp[i] + " ";
            }

            writer.WriteLine(tmpStr);                            
        } 
        writer.WriteLine("Do you want to add an email address? (y/n)");
        strFromClient = reader.ReadLine();

    }    

}
    catch (Exception e)
    {
        Console.WriteLine("{0} Exception caught.", e);
    }

EDIT VOL 2

OK! After 2 hours of misery, I think I found the problam thanks to Phil Frost (the genius!) --- the problam is probably in the client... (Im souch an a-hole!).

The server does send 2 string in a row, but my stupid implementation of the client side doesn't show a message (which recived from the server) that doesn't follow a message sent by the client...

So once again I need your help. Here's a view of how I designed the client form: enter image description here

My lack of experience led me to connect to the server when the "connect to server" button is pressed, and only when the "send Message" button is pressed, a message from the server is desplayed. The problam is when 2 (or more) messages from the server are recived without sending a message from the client to the server- the client doesn't know that a new message is recived! Where do I suppose to recive the messages from the server? ('where' means under which function, for example- right now it happens in the sendMessage_click function).

thanks again for all the help so far!!

like image 937
omi Avatar asked Jan 15 '23 15:01

omi


1 Answers

This question is neither lousy nor trivial. You are touching an important point in protocol design.

AFAIK, there are 2 ways to skin this particular cat:

  • "Dialog" (your way) ... Request is followed by reply, is followed by next request and so on. This has the big advantage of being easy, but the big disadvantage of only one command per connection being processed at any point in time
  • "Async" (Both parties can send without waiting for an answer) ... This has the implementation difficulty, that you need some sort of request-ID to make it possible to know, which reply belongs to which request: Imagine the client sending two requests, the first taking longer to process than the second: The replies would be in a different order than the requests.

The choice between these variants is not allways an easy one, but the trend goes towards the async model.

Additional difficulties in the async flavour include a mechanism to make sure, only one message is sent at a time (interweaving messages will most likely result in an unparseable stream) and timeout considerations.

like image 154
Eugen Rieck Avatar answered Jan 18 '23 23:01

Eugen Rieck