Cross-process/network communication using a TCP socket

Source: Internet
Author: User
Tags goto int size unix domain socket htons

Read Aboutspeaker's book, said that although there is pipe, msgget, message queue, UNIX domain socket, or the process is recommended to use only TCP sockets to communicate.

The disadvantage of pipe is obstruction. Msgget disadvantage is that you cannot select. Mq_send can, but two-way communication to open two MQ. UNIX domain cannot cross the network. The advantages of TCP sockets are many, it is difficult to deal with subcontracting, but can be abstracted out. According to my project needs, my own design data packet format is:

MSG--3 Bytescmd--  1 Byteulen--4 Bytesclen--4 bytesurl          ---ulen bytescontent  --Clen Bytes


Aboutspeaker at last added Adler32 checksum, I did for the sake of simplicity; In order to find the starting position of the package, I refer to the Sync Word concept of mpeg pes and introduce "MSG" as the magic number identifier.

Attached code:

/*IPC using TCP socket TEST:GCC-G-wall stream_buffer.c-dtest_msg_buffer./a.out./a.out 127.0.0.1*/#include <stdio. h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <stdint.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/socket.h> #include < netinet/in.h> #include <netdb.h> #include <arpa/inet.h> #include <poll.h> #ifndef av_rb32#define                   AV_RB32 (x) (((uint32_t) ((const uint8_t*) (x)) [0] << 24) |                   ((const uint8_t*) (x)) [1] << 16) |                    ((const uint8_t*) (x)) [2] << 8) | ((const uint8_t*) (x)) [3])                            #endif #ifndef av_wb32#define av_wb32 (p, darg) do {unsigned d = (darg); ((uint8_t*) (p))                       [3] = (d); ((uint8_t*) (p))                    [2] = (d) >>8; ((uint8_t*) (p))                   [1] = (d) >>16; ((Uint8_t*) (p)) [0] = (d) >>24; } while (0) #endiftypedef struct{int cmd;int Ulen, clen;uint8_t *url, *content;} Ctrl_msg_t;typedef struct{int RpoS, Wpos;int msize;uint8_t *buf;} streambuffer;static int ctrl_fd, serv_fd;static streambuffer *sb_in, *sb_out; streambuffer* sb_init (int msize) {Streambuffer *s = null;if (Msize < 1) {return NULL;} s = malloc (sizeof (*s)); if (!s) {return NULL;} S->rpos = S->wpos = 0;s->msize = Msize;s->buf = malloc (s->msize), if (!s->buf) {free (s); return NULL;} return s;} int Sb_destroy (Streambuffer *s) {if (S && s->buf) {free (S-&GT;BUF);} if (s) {free (s);} return 0;} int Sb_write (Streambuffer *s, uint8_t *data, int len) {/*return < 0 means fail.*/int size;if (!s | |!data | | Len < 0) { return-1;} if (S->msize-s->wpos >= len) {memcpy (s->buf + s->wpos, data, Len); S->wpos + = Len;} else if (S->msize-s->wpos + s->rpos >= len) {size = S->wpos-s->rpos;memmove (S->buf, S-&GT;BUF+S-&G T;rpos, size); S-&GT;RPOS = 0;s->wpos = size;memcpy (s->buf+s->wpos, data, Len); S->wpos + = Len;} else{printf ("SB buf full\n"); return-1;} return 0;} int Sb_read (Streambuffer *s, uint8_t *data, int len) {/*read actual read Bytes.*/int size;if (!s | |!data | | Len < 0) {RET Urn 0;} Size = s->wpos-s->rpos;if (Size > len) {size = Len;} memcpy (data, s->buf+s->rpos, size); S->rpos + = Size;return size;} static int CTL_MSG_CB (ctrl_msg_t *msg) {printf ("%s:%d '%s ' '%s ' \ n", (serv_fd? "Server": "Client"), Msg->cmd, Msg->url, msg->content); return 0;}    int ctl_msg_open (int server_fd) {struct sockaddr_in from_addr;    Socklen_t Len;    int FD;    len = sizeof (FROM_ADDR); memset (&from_addr, 0, Len);    FD = Accept (server_fd, (struct sockaddr *) &from_addr, &len);        if (FD < 0) {printf ("Error setup during accept%s\n", Strerror (errno));    return-1;    }printf ("New conn%s:%u\n", Inet_ntoa (FROM_ADDR.SIN_ADDR), Ntohs (From_addr.sin_port)); if (Fcntl (FD, F_SETFL, FCNTL (FD, F_GETFL) |    O_nonblock) < 0) {printf ("Set Non-block failed\n"); }CTRL_FD = Fd;return fd;} int ctl_msg_recv (void) {int len;uint8_t buf[1024];while (len = recv (ctrl_fd, buf, sizeof (BUF), 0)) > 0) {sb_write (sb_in , buf, Len);} return 0;} int ctl_msg_send (void) {int len;uint8_t *ptr = NULL; Streambuffer *SB = sb_out;if (!SB) {return-1;} Len = sb->wpos-sb->rpos;if (len <= 0) {return 1;} ptr = sb->buf + Sb->rpos;len = Send (CTRL_FD, PTR, Len, 0); if (len > 0) {sb->rpos + = Len;} return 0;} int Ff_ctl_open (unsigned short port) {int FD, tmp;struct sockaddr_in addr;memset (&addr, 0, sizeof (addr)); Addr.sin_f    amily = Af_inet;addr.sin_port = htons (port);    FD = socket (af_inet, sock_stream, 0);        if (FD < 0) {perror ("socket");    return-1;    } tmp = 1;    if (setsockopt (FD, Sol_socket, so_reuseaddr, &tmp, sizeof)) printf ("SetSockOpt so_reuseaddr failed\n");     if (Bind (FD, (struct sockaddr *) &addr, sizeof (addr)) < 0) {   printf ("Cant bind\n");        Close (FD);    return-1;        } if (Listen (FD, 5) < 0) {perror ("listen");        Close (FD);    return-1; } if (Fcntl (FD, F_SETFL, Fcntl (FD, F_GETFL) |    O_nonblock) < 0) {printf ("Set non block failed\n");    }SERV_FD = fd;sb_in = Sb_init (8096); sb_out = Sb_init (8096); return FD;} int Ff_ctl_open2 (char *ip, unsigned short port) {int fd;struct sockaddr_in addr;memset (&addr, 0, sizeof (addr)); addr . sin_family = Af_inet;addr.sin_port = htons (port), if (Inet_aton (IP, &addr.sin_addr) = = 0) {printf ("Bad ip '%s ' \ n        ", IP);    return-1;    } FD = socket (af_inet, sock_stream, 0);        if (FD < 0) {perror ("socket");    return-1;       } if (Connect (fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) {printf ("Cant connect to IP '%s ' \ n", IP);    return-1; } if (Fcntl (FD, F_SETFL, Fcntl (FD, F_GETFL) |    O_nonblock) < 0) {printf ("Set non block failed\n"); }CTRL_FD = Fd;sb_in = Sb_init (8096); sb_out = Sb_init (8096); return FD;} int ff_ctl_recv (void) {/*unpack sb_in and dispatch messages in It.*/streambuffer *SB = sb_in;uint8_t *ptr, *end;static Ctrl _msg_t msg = {0};if (!SB) {return-1;} ptr = sb->buf + sb->rpos;end = sb->buf + sb->wpos;while (ptr + 4 < end) {if (Msg.url) goto content;if (Msg.clen) Goto url;if (Msg.ulen) goto clen;if (msg.cmd) goto ulen;if (memcmp (PTR, "MSG", 3)) {ptr + = 3;continue;} PTR + = 3;msg.cmd = Ptr[0];p tr + 1;if (ptr >= end) Break;ulen:msg.ulen = Av_rb32 (PTR);p tr + = 4;if (ptr >= end) break;cle N:msg.clen = Av_rb32 (PTR);p tr + = 4;if (ptr >= end) break;url:if (Msg.ulen > 0 && ptr + msg.ulen <= end) {msg. url = malloc (msg.ulen+1); memcpy (Msg.url, PTR, Msg.ulen); Msg.url[msg.ulen] = 0;ptr + = Msg.ulen;} if (PTR >= end) break;content:if (Msg.clen > 0 && ptr + msg.clen <= end) {msg.content = malloc (msg.clen+1); me mcpy (Msg.content, PTR, Msg.clen); Msg.content[msg.clen] = 0;ptr + = MSG.CLEN;CTL_MSG_CB (&msg); free (msG.url); free (msg.content); memset (&msg, 0, sizeof (msg));}} Sb->rpos = Ptr-sb->buf;return 0;} int ff_ctl_send (int cmd, uint8_t *url, uint8_t *content) {int Ulen, clen;uint8_t *ptr, buf[64]; Streambuffer *SB = sb_out;if (!SB | |! ( 0 <= cmd && cmd <= 9)) {return-1;} Ulen = strlen ((char*) URL); Clen = strlen ((char*) content);p tr = buf;ptr + = sprintf ((char*) PTR, "MSG"); *ptr = (uint8_t) cmd;p TR + = 1; Av_wb32 (PTR, Ulen);p tr + = 4; Av_wb32 (PTR, Clen);p tr + = 4;sb_write (SB, buf, Ptr-buf), Sb_write (SB, URL, Ulen), Sb_write (SB, content, Clen); return 0;}  #if defined (test_msg_buffer) static int strip (char *str) {int n = strlen (str); while (n > 0 && (str[n-1] = = ' \ r ' | | Str[n-1] = = ' \ n ')) {str[--n] = 0;} return n;} int main (int ac, char **av) {int ret, FD, is_server = 1;int peer_fd = 0;if (ac! = 2) {printf ("Start server\n");} Else{is_server = 0;} if (is_server) {fd = Ff_ctl_open (5678);} ELSE{FD = Ff_ctl_open2 (av[1], 5678);} struct POLLFD *entry, table[8] = {{0}};for (;;) {entry = Table;if (FD) {entRY-&GT;FD = FD; Entry->events = pollin|        Pollout; entry++;}        if (PEER_FD) {entry = TABLE;ENTRY-&GT;FD = PEER_FD; Entry->events = pollin|        Pollout; entry++;}        Do {ret = poll (table, entry-table, 1000);  } while (Ret < 0), for (entry = table; entry->fd; ++entry) {if (Entry->revents & Pollin) {if (Is_server && ENTRY-&GT;FD = = FD && peer_fd <= 0) {peer_fd = Ctl_msg_open (FD);} Else{ctl_msg_recv (); Ff_ctl_recv ();}}     else if (entry->revents & pollout) {char line[128] = "";p rintf (">"); Fflush (stdout); fgets (line, sizeof (line), stdin), strip (line), Ff_ctl_send (2, (uint8_t*) "cmd", (uint8_t*) line); Ctl_ Msg_send ();}}} #endif

Both the server and the client are blocked in Fgets, and the message is displayed when the return is hit. Can be modified to the thread input. However, my final application scenario is not to deal with this and I have achieved the goal of self-testing.



Cross-process/network communication using a TCP socket

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.