linux下c语⾔使⽤socket进⾏线程间的通信
c语言struct用法例子socket起源于Unix,⽽Unix/Linux基本哲学之⼀就是“⼀切皆⽂件”,都可以⽤“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的⼀个实现, socket即是⼀种特殊的⽂件,⼀些socket函数就是对其进⾏的操作(读/写IO、打开、关闭).
说⽩了Socket是应⽤层与TCP/IP协议族通信的中间软件抽象层,它是⼀组接⼝。在设计模式中,Socket其实就是⼀个门⾯模式,它把复杂的TCP/IP协议族隐藏在Socket接⼝后⾯,对⽤户来说,⼀组简单的接⼝就是全部,让Socket去组织数据,以符合指定的协议。
注意:其实socket也没有层的概念,它只是⼀个facade设计模式的应⽤,让编程变的更简单。是⼀个软件抽象层。在⽹络编程中,我们⼤量⽤的都是通过socket实现的。
使⽤套接字除了可以实现⽹络间不同主机间的通信外,还可以实现同⼀主机的不同进程间的通信,且建⽴的通信是双向的通信。socket进程通信与⽹络通信使⽤的是统⼀套接⼝,只是地址结构与某些参数不同。
其主要流程如下:
⼀. 创建socket
创建socket,类型为AF_LOCAL或AF_UNIX,表⽰⽤于进程通信:
调⽤函数socket(),其原型如下:
int socket(int domain, int type, int protocol);
参数:
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);
以下为简单的,socket本地进程间通讯的例⼦:
1. 服务端
1.
2.
#include <stdio.h>
3.
#include <sys/types.h>
4.
4.
#include <sys/socket.h>
5.
#include <sys/un.h>
6.
7.
#define CAN_SERVICE "CAN_SERVICE"
8.
int main(void) 9.
{
10.
int ret;    11.
int len;  12.

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。