看了陈硕的书,说虽然有pipe, msgget, message queue, unix domain socket, 还是建议进程间只用tcp socket来通信。
pipe的缺点是阻塞。msgget缺点是不能select。mq_send可以,但是双向通信要开两个mq。unix domain不能跨网络。tcp socket优点很多,就是处理分包比较麻烦些,不过可以抽象出来。根据我的项目需要,自己设计的数据封包格式为:
MSG -- 3 Bytes
cmd -- 1 Byte
ulen -- 4 Bytes
clen -- 4 Bytes
url --- ulen Bytes
content -- clen Bytes
陈硕在最后加了adler32 checksum, 我为了简便没有;为了便于找到包的开始位置,我参考了mpeg pes的sync word概念,引入"MSG"作为magic number标识。
附代码:
/*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)
#endif
typedef 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;
StreamBuff