行业知识
嵌入式学习——3——域套接字UNIX
1、域套接字UNIX
1、域套接字是最原始的套接字通信方式,是完成同一主机之间多个进程间通信
()2、由于不需要跨主机进行通信了,那么就无需使用ip地址和端口号了
3、通信本质:依然使用的是内核空间
()4、域套接字的通信介质为套接字文件 bcd-lsp
5、域套接字也分为流式域套接字和报式域套接字
6、跟网络通信中相关函数的区别
#include
#include
int socket(int domain, int type, int protocol);
功能:为网络通信提供一个端点,并返回该端点的文件描述符,文件描述符使用原则为最小未分配原则
参数:
domain:通信域,可以选择协议族
Name Purpose Man page
AF_UNIX, AF_LOCAL 非跨主机通信 详细信息请看 man 7 unix
type: 指定通信语义,常用的通信语义如下
SOCK_STREAM 支持传输层的TCP通信方式
SOCK_DGRAM 支持传输层的UDP通信方式
SOCK_RAW 支持原始套接字通信
protocol: 当第二个参数中没有指定对应传输协议时,第三个参数要指定,如果第二个参数中已经确定了传输协议,那么第三个参数填0即可
1.如果参数type是 SOCK_STREAM或SOCK_DGRAM时,参数protocol可以填0
2.如果参数type没有指定是TCP还是UDP通信时,第三个参数protocol可以使用 IPPROTO_TCP或IPPROTO_UDP来确定
返回值:成功返回一个新的套接字文件描述符,失败返回-1 并置位错误码
7、地址信息结构体的不同
#include
#include
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:为给定的套接字文件描述符绑定IP地址和端口号
参数:
sockfd :要被绑定的套接字文件描述符
addr : 通用地址信息结构体,实际的地址信息,取决于地址族,
AF_INET 参见 man 7 ip , ‘
’AF_UNIX 参见 man 7 unix
对于本地通信的套接字地址信息结构体:
struct sockaddr_un {
sa_family_t sun_family; /* 通信域 */
char sun_path[108]; /* 套接字文件路径 */
};
/* 套接字文件路径 */ 必须是不存在的文件
addrlen: addr 的大小
返回值: 成功 0,失败 -1 并置位错误码
8、判断文件是否存在,以及删除文件
#include
int access(const char *pathname, int mode);
功能:判断给定的文件是否具有给定的权限
参数1:要判断的文件路径
参数2:要判断的权限
R_OK:读权限
W_OK:写权限
X_OK:可执行权限
F_OK:是否存在
返回值:如果文件存在并具有要求的所有权限,则返回0,否则返回-1并置位错误码
int unlink(const char *pathname);
功能:删除指定的文件
参数:要删除的文件路径
返回值:成功 0,失败 -1 并置位错误码
2、流式域套接字
2.1 服务器端实现
int main(){ //1、为通信创建一个端点 int sfd = socket(AF_UNIX, SOCK_STREAM, 0); if(sfd == -1) { perror("socket error"); return -1; } //判断要绑定的套接字文件是否存在? if(access("./unix", F_OK) == 0) { //说明文件存在,要将其删除 if(unlink("./unix") ==-1) { perror("unlink error"); return -1; } } //2、绑定ip和端口号 //2.1 准备地址信息结构体 struct sockaddr_un sun; sun.sun_family = AF_UNIX; //通信域 strcpy(sun.sun_path , "./unix"); //套接字文件路径 //2.2 绑定工作:必须绑定一个不存在的套接字文件 if(bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) ==-1) { perror("bind error"); return -1; } printf("bind success\n"); //3、将套接字设置成被动监听状态 if(listen(sfd, 128)==-1) { perror("listen error"); return -1; } printf("listen success\n"); //4、阻塞等待客户端的连接 //4.1 定义用于接受客户端信息的容器 struct sockaddr_un cun; socklen_t addrlen = sizeof(cun); int newfd = accept(sfd, (struct sockaddr*)&cun, &addrlen); if(newfd == -1) { perror("accept error"); return -1; } printf("[%s]:发来连接请求\n", cun.sun_path); //5、与客户端进行相互通信 char rbuf[128] = ""; //读取消息内容的容器 while(1) { //清空容器 bzero(rbuf, sizeof(rbuf)); //从套接字中读取数据 //int res = read(newfd, rbuf, sizeof(rbuf)); int res = recv(newfd, rbuf, sizeof(rbuf), 0); if(res == 0) { printf("客户端已经下线\n"); break; } //将读取的消息展示出来 printf("[%s]:%s\n", cun.sun_path, rbuf); //将收到的消息处理一下,回复给客户端 strcat(rbuf, "*_*"); //讲消息发送给客户端 send(newfd, rbuf, strlen(rbuf), 0); printf("发送成功\n"); } //6、关闭套接字 close(newfd); close(sfd); return 0;} 2.2 客户端实现
int main(){ //1、创建用于通信的套接字文件描述符 int cfd = socket(AF_UNIX, SOCK_STREAM, 0); if(cfd == -1) { perror("socket error"); return -1; } //判断要绑定的套接字文件是否存在? if(access("./linux", F_OK) == 0) { //说明文件存在,要将其删除 if(unlink("./linux") ==-1) { perror("unlink error"); return -1; } } //2、绑定IP地址和端口号 //2.1 填充客户端地址信息结构体 struct sockaddr_un cun; cun.sun_family = AF_UNIX; strcpy(cun.sun_path, "./linux"); //2.2 绑定 if( bind(cfd, (struct sockaddr*)&cun, sizeof(cun)) ==-1) { perror("bind error"); return -1; } printf("bind success\n"); //3、连接服务器 //3.1 准备对端地址信息结构体 struct sockaddr_un sun; sun.sun_family = AF_UNIX; strcpy(sun.sun_path, "./unix"); //3.2 连接服务器 if(connect(cfd, (struct sockaddr*)&sun, sizeof(sun))==-1) { perror("connect error"); return -1; } printf("connect success\n"); //4、数据收发 char wbuf[128] = ""; char rbuf[128] = ""; while(1) { //从终端上获取要发送的数据 fgets(wbuf, sizeof(wbuf), stdin); wbuf[strlen(wbuf)-1] = '3、报式域套接字
'; //将读取的换行改成' 3.1 服务器端实现
' //将数据发送给服务器 send(cfd, wbuf, strlen(wbuf), 0); printf("发送成功\n"); //接收服务器发来的消息 bzero(rbuf, sizeof(rbuf)); recv(cfd, rbuf, sizeof(rbuf), 0); printf("服务器发来的消息为:%s\n", rbuf); } //5、关闭套接字 close(cfd); return 0;} int main(int argc, const char *argv[]){ //1、创建用于通信的套接字文件描述符 int sfd = socket(AF_UNIX, SOCK_DGRAM, 0); if(sfd == -1) { perror("socket error"); return -1; } //判断要绑定的套接字文件是否存在? if(access("./unix", F_OK) == 0) { //说明文件存在,要将其删除 if(unlink("./unix") ==-1) { perror("unlink error"); return -1; } } //2、绑定IP地址和端口号 //2.1 填充地址信息结构体 struct sockaddr_un sun; sun.sun_family = AF_UNIX; strcpy(sun.sun_path, "./unix"); //2.2 绑定 if(bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) ==-1) { perror("bind error"); return -1; } printf("bind success\n"); //3、数据收发 char rbuf[128] = ""; //准备接受对端的地址信息 struct sockaddr_un cun; socklen_t addrlen = sizeof(cun); while(1) { //清空容器 bzero(rbuf,sizeof(rbuf)); //读取数据 recvfrom(sfd, rbuf, sizeof(rbuf), 0, (struct sockaddr*)&cun, &addrlen); printf("[%s]:%s\n", cun.sun_path, rbuf); //将收到的消息,加个笑脸回过去 strcat(rbuf, "*_*"); if(sendto(sfd, rbuf, strlen(rbuf), 0, (struct sockaddr*)&cun, sizeof(cun))==-1) { perror("write error"); return -1; } printf("发送成功\n"); } //4、关闭套接字 close(sfd); return 0;} 3.2 客户端实现
int main(int argc, const char *argv[]){ //1、创建用于通信的套接字文件描述符 int cfd = socket(AF_UNIX, SOCK_DGRAM, 0); if(cfd == -1) { perror("socket error"); return -1; } //2、绑定套接字文件 //2.1 填充地址信息结构体 struct sockaddr_un cun; cun.sun_family = AF_UNIX; strcpy(cun.sun_path, "./linux"); //判断要绑定的套接字文件是否存在? if(access("./linux", F_OK) == 0) { //说明文件存在,要将其删除 if(unlink("./linux") ==-1) { perror("unlink error"); return -1; } } //2.2 绑定 if(bind(cfd, (struct sockaddr*)&cun, sizeof(cun)) ==-1) { perror("bind error"); return -1; } printf("bind success\n"); //3、数据收发 char wbuf[128] = ""; //填充服务器的地址信息结构体 struct sockaddr_un sun; sun.sun_family = AF_UNIX; strcpy(sun.sun_path, "./unix"); char rbuf[128] = ""; while(1) { //清空容器 bzero(wbuf,sizeof(wbuf)); bzero(rbuf, sizeof(rbuf)); //从终端上获取信息 fgets(wbuf, sizeof(wbuf), stdin); wbuf[strlen(wbuf)-1] = 0; //讲消息发送给服务器 sendto(cfd, wbuf, strlen(wbuf), 0, (struct sockaddr*)&sun, sizeof(sun)); printf("发送成功\n"); //接受服务器发来的消息 recvfrom(cfd, rbuf, sizeof(rbuf), 0,NULL, NULL); printf("收到服务器消息为:%s\n", rbuf); } //4、关闭套接字 close(cfd); return 0;}
上一篇:关于服务器的记录怎么查?