4

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!!

5
  • 3
    One thing to quickly learn - if you're using TCP, it's stream oriented - if you want "messages" (such as strings), you need to implement this concept yourself - otherwise, the server might send two strings, but the client may receive that in one, two, or more calls to Read(). Even if they receive it in two, it might be half of the first string, followed by the second half of the first and the second string joined together. Whatever is receiving needs to have some way of knowing how much message to read (fixed length or length prefix) and to keep calling Read() until they get it. Commented Dec 31, 2012 at 14:52
  • I know very little about C#, so this is just a stab in the dark, but could it be that the output is buffered? What happens if you flush immediately after WriteLine? Commented Dec 31, 2012 at 15:45
  • flushing, doesnt help... (anyway its set on autoflush). tnx anyway :) Commented Dec 31, 2012 at 15:59
  • 1
    Huh. I'd check with a debugger, or some at least some print statements, that writer.WriteLine("Do you want to add an email address? (y/n)"); is actually executed. I don't see why it wouldn't be, but you never know. Are you absolutely sure there is nothing wrong with the client? Can you verify what happens on the network with wireshark, tcpdump, etc? Commented Dec 31, 2012 at 16:11
  • Wow phil, I think you really helped me... I think my problam is that the client doesnt refresh itself when getting the message... if so, I will declare you are a genius... I'll try to fix it now- BRB! Commented Dec 31, 2012 at 16:41

3 Answers 3

6

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.

Sign up to request clarification or add additional context in comments.

3 Comments

+1. Exactly. It is not about "Client Server Technology" in General, but a choise. Do you run a stream of commands and data in both directions, or do you have a Dialog (request/Response). Easier, but - well, at the end it depends what you NEED. you may even have multiple connectiosn, like I do - one command, one data. Command: Dialog, data: stream from Server to Client. The command includes stuff like "start sending updates on X", which will return a "OK" or "FAILURE". This really is a design choice. WHich the data usage basically will require.
Well, as I mentioned, I just started learning client-server programming, and my mistake i guess was to try writing my first code using an asinc approach... hope next time I'll be wiser and think before... anyway, now its too late- i dont have the courage to start the program all over using dialog approach :) THANK YOU!
@omi It might be harder this way, but you will get more out of it.
2

Yes, the server can send two strings in a row. But probably not if your server is blocked on read(). Perhaps if you included some more details about your program, a more specific answer could be provided.

Comments

1

In TCP the client-to-server and server-to-client channels are two independent streams. Either party can send at any time.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.