Client Server Relationship Confusion - c#

I have 5 computers that control different hardware. One of the five is the main controller for the other 4. I need to send commands from the main controller to the 4 slave controllers over TCPIP. I have very limited experience with Socket programming.
In the system I have which would be the client and which would be the server? It would seem to me that in the configuration I have the line between server and client may be skewed. Both sides need to send and receive commands, is there really a separation of client and server or is that just the convention? Can I have both endpoints as a client and server at the same time using the same socket? Essentially can I have both ends listening and sending requests?
I'm referencing the example code on MSN.
Asynchronous Server Socket
Asynchronous Client Socket

As far as socket connections go, who is the client and who is the server is just a matter of who accepts connections (the server) and who initiates a connect request (the client).
Once the connection is established, traffic can go in either direction (both client and server can send and/or receive data).

Your main controller is the Server. When it comes online it listens for your slaves to announce that they are online. They do this by connecting to the Server as Clients. The Server will Accept the connections.
If each slave performs some special function then you should have a message that the client can send to the server that indicates this function. If all of the slaves are required for the system to function properly then you will need to wait for all of the slaves to announce their distinct functions.
Your Server would then be able to send messages to a distinct Client or broadcast to all Clients. Each Client would only be able to send messages to the Server. If client-to-client communication is necessary you would probably implement message forwarding in the Server. This way, your Clients do not need to know the addresses of the other clients. They would only need to know their function, which would be used to route the messages to the appropriate Client.
I'm basically saying that you need to define a protocol by which your nodes will to communicate. This protocol will dictate which one of the nodes will be the Server and which of the nodes will be the Clients.
If your protocol turns out to be more appropriate for peer-to-peer instead of client-server you might want to consider using UDP instead of TCP.

Related

Grpc - send message from one client to another client that is connected to the same server

Is it possible to send message from one client to another client that is connected to the same server?
I want send data from one client to server Then send to specific client. I think I need to get client ID but I dont know how to get this id and how to send this message to that client from server.
I have a sample here. This is a chat server-client application. Multiple clients can connect to the server. When a client writes a message, the server simply broadcasts it for all clients who are receiving server stream RPC.
https://github.com/cactuaroid/GrpcWpfSample
See these server side implementation. When a client calls Subscribe(), it awaits m_chatService.Added event. When a client calls Write(), it raises the event and event args ChatLog is written on responseStream.
https://github.com/cactuaroid/GrpcWpfSample/blob/f6e8c4b2493c23cdcbaffeca29b5bb6705fbe95c/GrpcWpfSample.Server/Grpc/ChatServiceGrpcServer.cs
https://github.com/cactuaroid/GrpcWpfSample/blob/f6e8c4b2493c23cdcbaffeca29b5bb6705fbe95c/GrpcWpfSample.Server/Model/ChatService.cs
You can add your logic such as specifying channel name to subscribe/write, or define OpenChannel(string password) to be called by client at the first time so that server can bind the client IP address to the channel, whatever as you like.
There's no special gRPC feature that would allow you to do this (all RPC are between a server and a client, there's no "broadcast" or "selective broadcast" feature to reach out to other clients connected to the same server.
The logic you want is something that can definitely be implemented and but details of such solution depend on your need. A naive approach that might work is e.g. this:
each client opens a bidi-streaming call to the server
server keeps a directory of connected clients
once server receives a message from a client, it selects which client it should forward to based on the directory.
server forwards the message to a client.
Needless to say this setup feels a bit complicated (you're basically implementing your own network protocol on top of gRPC), so even though it might be just the right thing for you to do, it would make sense to think about how to simplify the protocol so that you can use features directly supported by gRPC.

c# and networking - Client listening and server send and most efficient C# socket networking?

I'm working on a game that depends on the standard System.Net.Sockets library for networking. What's the most efficient and standardized "system" I should use? Should the client send data requests every set amount of seconds, when a certain event happens? My other question, is a port forward required for a client to listen and receive data? How is this done, is there another socket created specifically for listening only on the client? How can I send messages and listen on the same socket on the client? I'm having a difficult time grasping the concept of networking, I started messing with it two days ago.
Should the client send data requests every set amount of seconds, when a certain event happens?
No. Send your message as soon as you can. The socket stack has algorithms that determine when data is actually sent. For instance the Nagle algorithm.
However, if you send a LOT of messages it can be beneficial to enqueue everything in the same socket method call. However, you need to send several thousand of messages per client and second for that to give you any benefit.
My other question, is a port forward required for a client to listen and receive data?
No. Once a socket connection have been established it's bidirectional. i.e. both end points and send and receive information without screwing something up for the other end point.
But to achieve that you typically have to use asynchronous operations so that you can keep receiving all the time.
How is this done, is there another socket created specifically for listening only on the client?
The server has a dedicated socket (a listener) which only purpose is to accept client sockets. When the listener have accepted a new connection from a remote end point you get a new socket object which represents the connection to the newly connected endpoint.
How can I send messages and listen on the same socket on the client?
The easiest way is to use asynchronous receives and blocking sends.
If you do not want to take care of everything by yourself, you can try my Apache licensed library http://sharpmessaging.net.
Creating a stable, high quality server will require you to have a wealth of knowledge on networking and managing your objects.
I highly recommend you start with something smaller before attempting to create your own server from scratch, or at the very least play around with a server for a different game that's already made, attempt to improve upon it or add new features.
That being said, there are a few ways you can setup the server, if you plan on having more than a couple of clients you don't generally want them to all send data whenever they feel like it as this can bog down the server, you want to structure it in such a way that the client sends as little data as possible on a scheduled basis and the server can request more when its ready. How that's setup and structured is up to you.
A server generally has to have a port forwarded on the router in order for requests to make it to the server from the internet, and here is why. When your computer makes a connection to a website (stackoverflow for example) it sends out a request on a random port, the router remembers the port that you sent out on and remembers who sent it (you), when the server sends the information you requested back the router knows you wanted that data and sends it back to you, in the case of RUNNING a server there is no outbound request to a client (Jack for example), so the router doesnt know where jacks request is supposed to go. By adding a port forwarding rule in the router your saying that all information passed to port 25565 (for example) is supposed to go to your server.
Clients generally do not need to forward ports because they are only making outbound requests and receiving data.
Server Starts, server starts listening on port 25565
Client starts, client connects to server on port 25565 and initiates a connection
Server responds to client on whatever port the client used to connect (this is done behind the scenes in sockets)
Communication continues from here.

Is it OK to use a single port for fast IPC communication?

I am using async sockets and have a single IP address and port that my Server (Listener) and each (internal/ on machine) Client uses.
Every time new external data comes to the Server, it loops through its (internal) Clients and sends the data on via the same socket.
Might this cause a backlog? If I have 10 Clients will the last Client get his data considerably later than the first Client?
Is it possible to have Clients with different ports connecting to a single Server?
Yes, think of how HTTP works -- it's always on port 80! See here for an example

Testing UDP on localhost

I'm currently trying to make an online video game, which currently uses TCP to send packets. I want to use UDP, but I'm extremely new to UDP and I'm having some issues.
When I test my server/client(s) on the same computer (localhost), the packets seem to be interfering with each other.
For example, if the client sends a packet to the server (UDP, 127.0.0.1:1338), the client ends up receiving the packet, since the client is also listening for packets from 127.0.0.1 on port 1338. Similarly, when I try to test 2 clients and 1 server, the clients may send out packets which are meant for the server, but are picked up by the other client.
How can I test UDP on localhost since all packets are being received from/sent to 127.0.0.1:1338? Do I need to implement some sort of layer in my packets that distinguishes if the packet is meant for the server, or a specific client?
Only your Server should listen on the defined port number (1338). Each client should select a free port number and send the server this port number. The server has to store the client information and send then the packets to the clients in this client list.
The clients should also send a goodby packet when the client is closing to know on the server side which clients are still available and which aren't participating anymore.
You should also implement some kind of housekeeping in this client list. For example store the timestamp of the last received packet from the client and remove clients that haven't sent data for some time (crashed client, lost connection ...) from the list.
An additional layer will not help - because the server may never actually get the packet.
Make the ports on the server and client configurable. That way you could have different ports on the same machine for testing and change it when going to production. Just remember you need to configure both ports in both the client and server. This is a good practice anyway.
You still have another problem - of several clients residing on the same machine and listening to the same port. You can have a random port for each client (the client selects one in random and then notifies the server). Or you can try binding to different IP addresses (one will use 127.0.0.1 an another will use the real IP of the PC), but it's not extensible.
If you are going to use this in a LAN setup, then you can always filter the received packet based on the sender's address -- recvmsg() of UDP allows you to retrieve sender's address and port number. If you are going to use this in a WAN setup, then this likely would not be an issue unless you are trying to do multicast. And, even with multicast, duplciate packets are not send back to the receiver. You can use IP_MULTICAST_LOOP to disable this option.

When to use different ports for client-server application?

When will I normally need different ports for client-server communication?
(This question is for C# and general socket programming).
I have implemented and been using a simple C# client-server application. Basically:
server listens for client
on accepted/connected
server spawn client thread -
server waits for client to talk
client talk
server respond
client talk
server respond etc.
if client stops talking, then server blocks in NetworkStream.Read() mode forever in that spawned thread unless client-side disconnects.
I am now thinking of the situation where both sides keeps quiet until some event happen on either side then only will the client or server sends data across. As such both needs to be in NetworkStream.Read mode concurrently somehow and also be able to send to each other at the same time (if the event happens on both sides simultaneously).
Do we need different ports in this case or can both client and server be in NetworkStream.BeginRead mode without risking a problem with NetworkStream being in both writing and sending mode at the same time?
Thanks.
Excellent question. I have written more than one app with that architecture. When you need to have bi-directional communication, you need two connections (of course, in two different ports) between client and server:
Connection where requests flow from client to server
Connection where requests flow from server to client
That way, both sides will have a NetworkStream ready to be read. And you notice the level of independence between the two flows, allowing you more control over your bi-directional request handling code.

Categories

Resources