C # client-server protocol / model question

I am trying to conceptually work through a model for a client-server socket application, which I write in C # (both client and server). My server will have to process several clients at once, and preferably several requests from the client at once. I designed a container for my message, where I will send a fixed-length header at the beginning of each message that will contain (among other things) the length of the message. I have some experience with socket programming in C #, so it’s convenient for me to use asynchronous sockets.

The main thing that I encountered is conceptually, I need the client and server to be able to receive messages at any time. The client will establish a connection and remain β€œlogged in” (for example, an IM client), and he will need to both receive data at arbitrary points in time and make requests at arbitrary points in time. I also wanted part of my protocol to receive a response to every request made (whether from server to client or from client to server).

I would like to be able to use one socket if possible. I believe that I could do this work using two sockets, one for creating server-> client requests and one for client-> server requests, but I do not want unnecessary difficulties with two ports / connections. However, using a single socket, I'm not sure how to control the sending of requests and receive responses when they can alternate.

I cannot find examples of similar servers or clients in my search. Thanks to everyone who offers any ides.

+2
source share
2 answers

If you use TCP, then you will definitely have to have one socket for each client on the server side, as well as a socket for listening to connections. For UDP, you can do it all with one socket. Regardless, do the following for your single UDP socket or for each client TCP socket:

You have BeginReceive at any time and BeginWrite when the necessary event occurs (i.e. the user presses a button or a message appears stating that you need to do something).

EDIT: in response to your comment, the way I would handle this would be to include the request id in your header. Whenever sending a request (from either end) includes a unique value for this message. Use Dictionary<RequestId, RequestState> (with appropriate type substitutions) and see if the incoming message is associated with a previously existing request. In addition, you can specify that all identifiers with a high set of bits are requests coming from the client and identifiers with a high bit cleared from the server to avoid conflicts:

 Server Client Request 0x00 -------------> Starts processing Starts processing <------- (unrelated) Request 0x80 Request 0x00 complete <---- Sends response to 0x00 Sends response to 0x80 ---> Request 0x80 complete 

This is a system that uses the AOL OSCAR protocol for (possibly slow) state requests.

EDIT2: Hm, okay ... do you really want to block it? Something you could do is have a separate thread handling Send / Receive calls. This thread will communicate with the main thread through the thread-safe queue "send message" and a similar "received message" psuedo-queue. The reason I call psuedo last queue is because you would like the ability to output messages from the queue from the queue. The main thread places the message in the send queue, and then blocks the receive queue. Each time the socket stream updates the receive queue, the main stream wakes up and checks if there is a message that it wants. If this is the case, then it will be required (out of order) to complete the desired operation. If the message does not already exist, it will simply be blocked in the queue. When the operation is completed, it will only resume normal operation and receive messages in the queue from the receive queue and process them or do something else.

Does that make sense? I apologize if this is confusing ...

+2
source

Bidirectional sockets. You only need one socket to send data between two endpoints. But on the client, you probably need one stream constantly reading the socket, and a notification about some component or the sequence of received data, so it is processed elsewhere, and the other stream sends data through the same socket. So you have asynchronous communication.

But on the server side, you need to open a ServerSocket, which will bind to a TCP port and accept connections on this port; every connection you accept is a new socket. So you have a socket for each client, and you probably need one thread for each client.

You need to set the protocol for messages that you will send over the socket. You can either brew create your own protocol, or view it depending on what you want to do. Usually you first send two or four bytes with a length for the rest of the message, so the other side is aware to read that there are many bytes from the stream; this post. The start of a message is usually a type of message; in a very simple scenario, you can say that β€œ1” is a client request, β€œ2” is a server response, β€œ3” is a client echo, β€œ4” is a server response to a server, β€œ5” is an echo server, β€œ6 "is a client echo reply, etc. Thus, you receive a message, analyze it, and then you know its request from the client or the response to the message sent from the server, for example.

+3
source

Source: https://habr.com/ru/post/1333720/


All Articles