利用socket进行本地通信,必须包含两个头文件:
1 #include <sys/socket.h> // 用于socket创建等 2 #include <sys/un.h> // 包含本地socket的结构体
在socket通信中,建立socket一端称为服务器端,主动连接的一端称为客户端,建立过程如下:
一、服务端
1、建立socket,例:
1 srv_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
2、建立socket结构类型,例:
1 struct sockaddr_un srv_addr; 2 struct sockaddr_un clt_addr; 3 4 /*note: use abstract namespace, the first bit of sun_path must been set 0*/ 5 bzero(&srv_addr, sizeof(srv_addr)); 6 srv_addr.sun_family = AF_UNIX; 7 strcpy(srv_addr.sun_path, server_name); 8 srv_addr.sun_path[0]=0; 9 srv_len = strlen(server_name) + offsetof(struct sockaddr_un, sun_path);
PS:
—— server_name为字符串,即本次建立的socket服务的名称,客户端也是通过这个名字连接服务器的。
—— 上述是采用abstract namespace,好处是不需要知道socket服务的具体路径,可以通过名称(server_name)直接连,但是sun_path[0]必须置0,而且在赋值前,最好用bzero对服务端的sockaddr_un srv_addr进行置0。
3、绑定socket,例:
1 bind(srv_sockfd, (struct sockaddr*)&srv_addr, srv_len);
4、添加监听,第二个参数为允许连接的最大客户端数目,例:
1 listen(srv_sockfd, 1);
5、等待客户端连接,例:
1 clt_len = sizeof(clt_addr); 2 clt_fd = accept(srv_sockfd,(struct sockaddr*)&clt_addr, &clt_len);
PS:若此时无客户端连接,accept会阻塞在这里,直到有客户端连接上。
6、与客户端进行通信,使用read/write函数,例:
1 char chk; 2 read(clt_fd, &chk, 1); // read information which is send by client, length is 1 set by the 3th param. 3 4 char chk1 = 'V'; 5 write(clt_fd, &chk1, 1); // send 'V'(length is 1) to client.
PS:
—— 这里发送和接受都用的是客户端节点:clt_fd。
—— read和write是一一对应的,服务端不写,客户端读不到,反之亦然;服务端写一次,客户端也只能读一次,否则第二次读取会阻塞,直到服务端再次写入,反之亦然。
二、客户端
1、建立socket,例:
1 clt_fd = socket(AF_UNIX, SOCK_STREAM, 0);
2、创建socket结构类型,例:
1int clt_len; 2struct sockaddr_un client; 3 client.sun_family = AF_UNIX; 4 strcpy(client.sun_path, server_name); 5 client.sun_path[0]=0; 6 clt_len = strlen(server_name) + offsetof(struct sockaddr_un, sun_path);
PS: 这里的server_name需要和服务端是相同的。
3、连接服务端,例:
1 connect(clt_fd, (struct sockaddr *)&client, clt_len);
4、连接上以后,就可以利用read/write函数与服务端进行通信了。
完整代码这里就不写了,把上述代码组起来就OK了,需要注意的是:先accept,再connect,因为connect是非阻塞的,没有服务端接收的话,connect会直接返回,导致连接不成功。