I've been working on a complex server-client system in C and I'm not sure how to implement the socket communication.
In a nutshell, the system is a server application which communicates with a database and uses a UNIX socket to communicate with one or more child processes created with fork(). The purpose of the children is to run game servers. The process of launching a game server is like this:
The server/"manager" identifies a game server in the database that is to be made. (Assume database communication is already sorted.)
The manager forks a child (the "game controller").
The game controller sets up two pipe pairs, then forks, replacing its child's stdin with a pipe, and it's stdout and stderr with another pipe.
The game controller's child then runs execlp() to begin running the actual game server executable.
My experience with sockets is fairly minimal. I have used select() on a server application before to 'multiplex' numerous clients, as demonstrated by the simple example in the GNU C documentation here.
I now have a new challenge, as the system must be able to do more: the manager needs to be able to arbitrarily send commands to the game controller children (that it will find by periodically checking the database) and get replies, but also expect incoming arbitrary commands/errors from them and send replies back.
So, I need a sort-of "context" system, where sockets are meaningful only between themselves. In other words, when a command is sent from the manager to the game controller, each party needs to be aware of who is asking and know what the reply is (and, therefore, which command it is a reply to).
Because select() is only useful for knowing when we have incoming data, and a thread should block on it, would I need another thread that sends data and gets the replies? Will this require each game controller, although technically a 'client', to use a listening socket and use select() as well?
I hope I've explained the system and the problem concisely; I will add more detail if required. Thanks!
Ok, I am still not really sure I understand exactly where your trouble is, so I will just spout off some things about writing a client/server app. If I am off track, just let me know.
The way that the server will know which clients corresponds to which socket is that the clients will tell the server. Essentially, you need to have a log-in protocol. When the game controller connects to the server, it will send a message that says "Hi, i am registering as controller foo1 on host xyz, port abc..." and whatever else the server needs to know about its clients. The server will keep a data structure that maps sockets to client metadata, state, etc. Whenever it gets a new message, it can easily map from the incoming host/port to its metadata. Or your protocol can require that on each incoming message, the will client send the name it registered with as a field.
Handling the request/response can be done several ways. First lets deal with the networking part of it on the server side. One way to manage this, as you mentioned, is by using select (or poll, or epoll) to multiplex the sockets. This is actually usually considered the more complicated way to do things. Another way is to spawn off a thread (or fork a process, which is less common these days) for each incoming client. Each spawned thread can read its own assigned socket, responding to messages one at a time without worrying about the fact that there are other clients besides the own it is dealing with. This simple one to one thread to socket model breaks down if there are many clients, but if that is not the case, then it is worth consideration.
Part 2 really covers only the client sending the server a message, and the server replying. What happens when the server wants to initiate communication? How does it do it and how does the client handle it? Also, how do you model the model the communication at the application level, meaning assuming we have the read/write part down, how do we know what to send? You will probably want to model things in terms of state machines. There is also a lot more to deal with like what happens when a client crashes? What about when the server crashes? Also, what if you really have your heart set of using select, perhaps because you expect many client? I will try to add more to this answer tomorrow.
Related
I am writing a small server/client program. I am not sure how to use select() to choose between a client that already is connected to the server, and to add a new client.
i.e.: The server program will start and be listening for clients. How can I use a select statement to know whether the server is receiving from an existing client, or a new connection?
Does the server always have to listen() and accept() every new client?
Thank you.
Before getting your hands dirty dealing with a selector you should read something about Non-Blocking I/O or asynchronous networking. Basically what your selector does is loop through the file descriptors that you have created and check whether someone wants to perform one of the following actions:
Read
Write
Accept
Connect
I could go further into how it does but if you really do want to know please do search into reactor pattern and maybe how programming through events work.
Anyway, to detect a new connection or an already existing one might be trivial or not so trivial, depending on how much control you want to have on the actions performed.
First. You register your server socket on the selector. This socket will stay listening forever and when a client connects the accept event will be triggered and one selector cycle will occur. This will create another file descriptor that you will have to register in your selector.
From this point forward you have to control your connection intention. Do you want to read? Write? Not only this, since this is asynchronous programming and you can't or should not block the information will have to be transferred in chunks. It will be up to you to receive all the data chunks and coordinate all the file descriptors. This is the non-trivial part.
If you want to know anything else please say so and i will edit this answer.
I am working on a UDP server/client application.
I want my server to be able to handle 40 clients at a time. I have thought of creating 40 threads at server side, each thread handling one client. Clients are distinguished on the basis of IP addresses and there is one thread for each unique IP address.
Whenever a client sends some data to a server, the main thread extracts the IP address of the client and decides which thread will process this specific client. Is there a better way to achieve this functionality?
There are different approaches for scale able server application, one thread per client seems good if no of clients are not many, another most efficient approach to accomplish this task is to use thread pool. These threads are work as task base when ever you have any new task assign this task to free worker thread.
Take a look at this project, I think it is very helpful to start with: http://www.codeproject.com/Articles/16935/A-Chat-Application-Using-Asynchronous-UDP-sockets
With IPAddress.Any, we specify that the server should accept client
requests coming on any interface. To use any particular interface, we
can use IPAddress.Parse (“192.168.1.1”) instead of IPAddress.Any. The
Bind function then bounds the serverSocket to this IP address. The
epSender identifies the clients from where the data is coming.
With BeginReceiveFrom, we start receiving the data that will be sent
by the client. Note that we pass epSender as the last parameter of
BeginReceiveFrom, the AsyncCallback OnReceive gets this object via the
AsyncState property of IAsyncResult, and it then processes the client
requests (login, logout, and send message to the users). Please see
the code attached to understand the implementation of OnReceive.
A better way would be to use the Proactor pattern (take a look at Boost.Asio library), instead of creating thread per client. With such an approach your application would have much better scalability and performace (especially on platforms that have native async i/o)
Besides, with this technique the threading would be de-coupled from the concurrency, meaning that you don't necessarily have to mess with multi-threading with all its complications.
I have a question regarding on how to design the following system:
My system is built of several clients listening to an environment. When a audio threshold is breached they send their information to a server, that has children listening on each connection. The server needs information from all the clients to make the necessary calculations.
Currently the server is working in UNIX and has forked out connections. They are working independently.
What I want to do is to tell the parent (in the server) that information has been sent and it's now time to process it. How should I do it?
I'm thinking of possible different ways to do it:
Using signal()in Unix to somehow tell the parent that something has happened
Convert to Threads and use some wait and notify functions
The signaling is preferable but I cannot figure out how to do it efficiently. Because the following can happen in my system:
If all the clients successfully sent information to their children of the server, how can I tell the parent that I'm ready in a efficient way? Don't know/I'm uncertain of how it will process them.
The server may not receive information from all clients. So the parent must wait for awhile for all the children but not too long. So I'm guessing some sort of timer?
Doen't use fork, and don't use signals. Use a thread pool.
What about a Unix Domain Socket for an inter-processes communication between children and father?
http://en.wikipedia.org/wiki/Unix_domain_socket
As soon as a child receives data through the TCP connection, the same data will be forwarded to the father process through the Unix Domain Socket and the latter process will be instantly notified
I am trying to perform multithreading on a socket in C in order to develop a connector between two different software applications. I would like it to work in the following manner. One piece of software will start running as the server, it will be performing a variety of functions including listening for a socket connection on a designated port. This software will function by it self and only use data from the connected network socket when it is established and receiving reliable data. So for this piece I would like to be able to listen to a connection, and when one is made fork a process and when data is received from this socket set some variable that will be used by some other update thread to notify it that it has these extra precision information that can be considered. On the other side of this equation I want to create a program that when it boots up will attempt to connect to the port of the other application, once this connects it will then simply call a function that will send out the information in non blocking fashion. My whole goal is to create a connector that will allow the programmers of the other two pieces of code to feel as tho they aren't dealing with a socket what so ever.
I have been able to get multi threaded socket communication going but I am now trying to modify this so it will be usable as I have described and I am confused as to how to avoid multiple access to that variable that will notify the system on the server side that the data has arrived as well as create the non-blocking interaction on the client side. Any help ill be appreciated.
-TJ
The question is not so clear to me, but if you need to make different pieces of software talking easily you can consider using a framework message library like ZeroMQ www.zeromq.org
It seems like you have a double producer-consumer problem here:
Client side Server
producer -> sender thread -> receiver thread -> consumer thread
In this case, the most useful data structure to use is a blocking queue on both sides, like intel TBB's concurrent_bounded_queue.
This allows you to post tasks from one thread and have another thread pull the data when it's available in a thread-safe manner.
I am writing a simple instant messenger program in C on Linux.
Right now I have a program that binds a socket to a port on the local machine, and listens for text data being sent by another program that connected to my local machine IP and port.
Well, I can have this client send text data to my program, and have it displayed using stdout on my local machine; however, I cannot program a way to send data back to the client machine, because my program is busy listening and displaying the text sent by the client machine.
How would I go about either creating a new process (that listens and displays the text sent to it by the client machine, then takes that text and sends it to the other program's stdout, while the other program takes care of stdin being sent to the client machine) or create 2 programs that do the separate jobs (sending, receiving, and displaying), and sends the appropriate data to one another?
Sorry if that is weirdly worded, and I will clarify if need be. I looked into exec, execve, fork, etc. but am confused as to whether this is the appropriate path to look in to, or if there is a simpler way that I am missing.
Any help would be greatly appreciated, Thank you.
EDIT: In retrospect, I figured that this would be much easier accomplished with 2 separate programs. One, the IM server, and the others, the IM clients.
The IM Clients would connect to the IM server program, and send whatever text they wanted to the IM server. Then, the IM server would just record the data sent to it in a buffer/file with the names/ip's of the clients appended to the text sent to it by each client, and send that text (in format of name:text) to each client that is connected.
This would remove the need for complicated inter-process/program communication for stdin and stdout, and instead, use a simple client/server way of communicating, with the client programs displaying text sent to it from server via stdout, and using stdin to send whatever text to the server.
With this said, I am still interested in someone answering my original question: for science. Thank you all for reading, and hopefully someone will benefit from my mental brainstorming, or whatever answers come from the community.
however, i cannot program a way to send data back to the client machine, because my program is busy listening and displaying the text sent by the client machine.
The same socket that was returned from a listening-socket by accept() can be used for both sending and receiving data. So your socket is never "busy" just because you're reading from it ... you can write back on the same socket.
If you need to both read and write concurrently, then share the socket returned from accept() across two different threads. Since two different buffers are being used by the networking stack for sending and receiving on the socket, a dedicated thread for reading and another dedicated thread for writing to the socket will be thread-safe without the use of mutexes.
I would go with fork() - create a child process and now you have two different processes that can do two different things on two different sockets- one can receive and the other can send. I have no personal experience with coding a client/server like this yet, but that would be my first stab at solving your issue...
As #bdonlan mentioned in a comment, you definitely need a multiplexing call like select or preferably poll (or related syscalls like pselect, ppoll ...). These multiplexing calls are the primitive to wait on several channels at once (with pselect and ppoll able to atomically wait for both I/O events and signals). Read also the select tutorial man page. Of course, you can wait for several file descriptors, and you can wait for both reading & writing abilities (even on the same socket, if needed), in the same select or poll syscall.
All event-based loops and frameworks are using these multiplexing calls (like poll or select). You could also use libevent, or even (particularly when coding a graphical user interface application) some GUI toolkit like Gtk or Qt, which are all based around a central event loop.
I don't think that having a multi-process or multi-threaded application is useful in your case. You just need some event loop.
You might also ask to get a SIGIO signal when data arrives on your socket using fcntl with F_SETOWN, but this is not very useful for you. Then you often want to have your socket non-blocking.