Unix Socket Essentials
Unix Socket Essentials
In a shell, there are 3 socket fds used when using sockets. 2 by the server: 1 to listen and establish connections (sersock), and 1 to
perform communication (consock). Then 1 on the client (clisock) which is used for communication.
See necessary includes on the bottom
Summary:
This is a very common form of interprocess communication that can be easily
parallelized on multiple threads to communicate with multiple clients, or just as easily utilized to
force clients to wait until the server is ready for another client. Like pipes, data is transferred as
individual bytes, usually utilizing a buffer to send large chunks at a time.
It is important when developing your application that you consider the communication
flow of the client-server connection as you approach your problem. For example, when the
connection is established, should the server write data to the client and then wait for a response
or should the client write data first?
For one of my projects, I had the client write data to the server. The type of
communication or request the client wanted to make could be 1 of 6 different things. In order for
the server to identify which request it was going to be, I had the client prepend their message
with one of these characters: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, or ‘5’. Then, the server would read exactly one
byte and use a switch to determine what action should be taken. This is a very informal
“protocol”, feel free to experiment and establish your own paradigm.
It is very important that the client sends the character ‘0’ instead of the integer 0,
because using string functions on the buffer would interpret the integer 0 as the null character
‘\0’ and produce undesirable results.
Note that this document is purely a supplement to the C/Linux manual pages for socket(), bind(),
listen(), accept(), read(), and write().
Steps to establishing a connection on the server:
1. Setup the address struct (this is used to identify where the socket will be placed in your
filesystem)
a. .sun_family (socketaddress_unix) = AF_UNIX
i. This is mandatory and the only option for .sun_family
b. .sun_path (so cketaddress_unix) = the (absolute or relative) path on your
filesystem to the socket you are going to create, this will be the same for client
and server
2. socket()
a. Creates a socket (returns a fd so you can use read(), write(), or other
system calls that use fd’s)
b. NOTE: the socket we are making here will not be used to perform communication
- it will only be used to establish a connection with a client(s)
3. bind()
a. Attempts to create a socket file at the path specified, will error if the file already
exists! (calling unlink(sock_path) will remove the file if it exists)
b. You will use sock_path on the client to refer to the same socket the server has
created
4. listen()
a. This tells the socket to listen for incoming connections, the 10 specifies how
many clients can be waiting to connect at a time
struct sockaddr_un addr;
int sersock;
int len = sizeof(addr);
memset(&addr, 0, len); // clear out the field
char sock_path[60];
strcpy(sock_path, getenv("HOME"));
strcat(sock_path, "/Desktop/.socket");
strcpy(sock_path, getenv("HOME"));
strcat(sock_path, "/Desktop/.socket");
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path)-1);