转自:https://blog.csdn.net/baidu_24553027/article/details/54912724服务器
使用套接字除了能够实现网络间不一样主机间的通讯外,还能够实现同一主机的不一样进程间的通讯,且创建的通讯是双向的通讯。socket进程通讯与网络通讯使用的是统一套接口,只是地址结构与某些参数不一样。网络
其主要流程以下:并发
客户端:dom
一. 建立socketsocket
建立socket,类型为AF_LOCAL或AF_UNIX,表示用于进程通讯:函数
调用函数socket(),其原型以下:ui
int socket(int domain, int type, int protocol);spa
参数:.net
domain:指定协议族,对于本地套接字来讲,值必须设置为AF_UNIX枚举值;线程
type:指定套接字类型,能够被设置为SOCK_STREAM(流式套接字)活SOCK_DGRAM(数据报式套接字)
protocol:指定具体的协议,应被设置为0
返回值为生成的套接字描述符。
对于本地套接字来讲,流式套接字(SOCK_STREAM)是一个有顺序的、可靠的双向字节流,至关于在本地进程之间创建起一条数据通道;数据报式套接字(SOCK_DGRAM)至关于单纯的发送消息,在进程通讯过程当中,理论上可能会有信息丢失、复制或者不按前后次序到达的状况,但因为其在本地通讯,不经过外界网络,这些状况出现的几率很小。
二. 设置socket参数
SOCK_STREAM式本地套接字的通讯双方均须要有本地地址,其中服务器端的本地地址须要明确指定,指定方法是使用struct sockaddr_un类型的变量
struct sockaddr_un{
sa_family_t sun_family; // AF_UNIX
char sun_path[UNIX_PATH_MAX]; // 路径名
}
三. 绑定
绑定要使用 bind 系统调用,其原形以下:
int bind(int socket, const struct sockaddr *address, size_t address_len);
参数
socket:服务端套接字描述符
address:须要绑定的服务端本地地址
address_len:本地地址的字节长度
四. 监听
服务器端套接字建立完毕并赋予本地地址值(名称,本例中为CAN_SERVICE)后,须要进行监听,等待客户端链接并处理请求,监听使用 listen 系统调用,接受客户端链接使用accept系统调用,它们的原形以下:
int listen(int socket, int backlog);
int accept(int socket, struct sockaddr *address, size_t *address_len);
参数
socket:表示服务器端的套接字描述符;
backlog 表示排队链接队列的长度(如有多个客户端同时链接,则须要进行排队);
address 表示当前链接客户端的本地地址,该参数为输出参数,是客户端传递过来的关于自身的信息;
address_len 表示当前链接客户端本地地址的字节长度,这个参数既是输入参数,又是输出参数。实现监听、接受和处理。
五. 链接
客户端须要socket系统调用connect()链接到服务端,其函数原型以下:
int connect(int socket, const struct sockaddr *address, size_t address_len);
参数
socket:客户端的套接字描述符
address:当前客户端的本地地址,是一个 struct sockaddr_un 类型的变量
address_len:表示本地地址的字节长度
五. 数据交互
不管客户端仍是服务器,都要和对方进行数据上的交互。一个进程扮演客户端的角色,另一个进程扮演服务器的角色,两个进程之间相互发送接收数据,这就是基于本地套接字的进程通讯。
循环读取客户端发送的消息,当客户端没有发送数据时会阻塞直到有数据到来。若是想要多个链接并发处理,须要建立线程,将每一个链接交给相应的线程并发处理。接收到数据后,进行相应的处理,将结果返回给客户端。发送和接收数据要使用 write 和 read 系统调用,它们的原形为:int read(int socket, char *buffer, size_t len);int write(int socket, char *buffer, size_t len);