Here's a quick and dirty example of how to have two threads communicating over a UNIX socket on Linux. These could have been two different processes, but I used threads so the example was more self contained. Note that this uses the gethrtime() function I described on another post.
/*
* gcc -pthread -lrt -O3 socket.c -o socket
*/
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <err.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#define SOCKET_FILE "/tmp/socket_file"
typedef struct {
char reply[256];
} socket_msg_t;
static volatile server_socket = 0;
void *
server_thread(void *arg)
{
socket_msg_t msg;
struct sockaddr_un addr;
int sock;
int conn_socket;
int max;
int nfds;
fd_set fds;
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "server failed to open socket\n");
return (NULL);
}
bzero(&addr, sizeof (addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOCKET_FILE, sizeof (addr.sun_path));
unlink(SOCKET_FILE);
if (bind(sock, (struct sockaddr *)&addr, sizeof (addr)) != 0) {
fprintf(stderr, "server can't bind\n");
close(sock);
server_socket = -1;
return (NULL);
}
if (listen(sock, 2) != 0) {
fprintf(stderr, "server can't listen\n");
close(sock);
server_socket = -1;
return (NULL);
}
server_socket = sock;
for (;;) {
FD_ZERO(&fds);
FD_SET(server_socket, &fds);
max = server_socket;
if ((nfds = select(max + 1, &fds, NULL, NULL, NULL)) == -1) {
if (errno == EINTR) {
continue;
}
close(server_socket);
server_socket = -1;
return (NULL);
}
if (!FD_ISSET(server_socket, &fds)) {
continue;
}
if ((conn_socket = accept(server_socket, NULL, NULL)) == -1) {
close(server_socket);
server_socket = -1;
return (NULL);
}
while (conn_socket != -1) {
if (read(conn_socket, (caddr_t)&msg, sizeof (msg)) !=
sizeof (msg)) {
fprintf(stderr, "server received bad msg\n");
conn_socket = -1;
}
snprintf(msg.reply, sizeof (msg.reply),
"replying at %ld\n", gethrtime());
if (write(conn_socket, (caddr_t)&msg,
sizeof (msg)) < 0) {
fprintf(stderr, "server failed to reply\n");
conn_socket = -1;
}
fprintf(stderr, "server replied\n");
}
close(conn_socket);
}
}
void *
client_thread(void *arg)
{
socket_msg_t msg;
struct sockaddr_un addr;
int cli_socket;
while (server_socket == 0) {
if (server_socket == -1) {
fprintf(stderr, "client exitting..\n");
break;
}
sleep(1);
}
sleep(1);
if ((cli_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "client failed to open socket\n");
return (NULL);
}
bzero(&addr, sizeof (addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOCKET_FILE, sizeof (addr.sun_path));
if (connect(cli_socket, (struct sockaddr*)&addr,
sizeof (addr)) == -1) {
fprintf(stderr, "client failed to connect\n");
return (NULL);
}
fprintf(stderr, "client connected\n");
while (server_socket != -1) {
if (write(cli_socket, &msg, sizeof (msg)) < 0) {
perror("");
fprintf(stderr, "client failed to write\n");
break;
}
if (read(cli_socket, &msg, sizeof (msg)) != sizeof (msg)) {
fprintf(stderr, "client failed to read\n");
break;
}
fprintf(stderr, "client received :: %s\n", msg.reply);
sleep (1);
}
fprintf(stderr, "client server_socket closed\n");
close(cli_socket);
}
int
main(int argc, char **argv)
{
pthread_t server, client;
if (pthread_create(&server, NULL, server_thread, NULL) != 0) {
perror("failed to create waiter thread");
return (1);
}
if (pthread_create(&client, NULL, client_thread, NULL) != 0) {
perror("failed to create signaler thread");
return (1);
}
pthread_join(server, NULL);
pthread_join(client, NULL);
return (0);
}
And some sample output:
client connected
server replied
client received :: replying at 16116710538870904
server replied
client received :: replying at 16116711539198484
server replied
client received :: replying at 16116712539583206
No comments:
Post a Comment