本地套接字
7-1简介
在Linux系统下,可以使用本地套接字(Unix域套接字)进行进程间通信。本地套接字是一种特殊类型的套接字,用于在同一主机上的进程之间进行通信。
7-2 创建本地套接字服务器的流程
可以使用TCP或UDP的方式来实现通信,使用TCP就得遵循TCP的流程,UDP就要遵循UDP的流程。
7-2-1使用TCP的本地套接字服务器流程
第一步:使用socket创建一个套接字,并且第一个参数为AF_UNIX,第二个为SOCK_STREAM (TCP)。
第二步:使用bind进行本地地址绑定,但是结构体要是struct sockaddr_un并且成员sun_family也要是AF_UNIX。而且要创建一个变量(详见代码)。然后bind中要使用struct sockaddr_un &进行强转。
第三步:使用listen函数监听套接字。
第四步:使用accept函数获得新连接。
第五步:对接收到的数据进行读写或者其他操作。
第六步:如果不需要停下来记得关闭acdept和socket创建的两个文件描述符。
7-2-2使用TCP的本地套接字客户端流程
第一步:创建套接字,并且第一个参数为AF_UNIX,第二位SOCK_STREAM (TCP)。
第二步:绑定本地地址。(不是必须的, 若无显示绑定会进行隐式绑定,但服务器不知道谁连接了)。
第三步:调用connect函数进行连接。
第四步:通信。
第五步:关闭第一步创建的描述符。
7-3 本地套接字服务端代码实例
点击查看代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/un.h>
int main()
{
//创建套接字,记得使用AF_UNIX
int lfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (lfd < 0) {
perror("创建套接字失败!");
exit(0);
}
struct sockaddr_un serv;//本地地址
struct sockaddr_un clie;//客户端地址
serv.sun_family = AF_UNIX;//记得使用UNIX
//创建一个变量,之后客户端需要访问这个变量才能进行本地通信
strcpy(serv.sun_path, "./server.sock");
//绑定
int ret = bind(lfd, (struct sockaddr*)&serv, sizeof(serv));
if (ret < 0) {
perror("bind error");
exit(0);
}
//监听
ret = listen(lfd, 10);
if (ret < 0) {
perror("listen error");
exit(0);
}
int n;
char data[100];
char serv_data[100] = "server susser!";
//建立连接
int len = sizeof(clie);
int cfd = accept(lfd, (struct sockaddr*)&clie, &len);
while (1) {
memset(data, 0x00, sizeof(data));
n = recv(cfd, data, sizeof(data), 0);
if (n < 0) {
perror("recv error!!!");
}
if (send(cfd, serv_data, sizeof(serv_data), 0) == -1) {
perror("send error!!!");
}
}
close(lfd);
return 0;
}
7-4 本地套接字客户端代码实例
点击查看代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/un.h>
int main()
{
//创建套接字,使用AF_UNIX
int cfd = socket(AF_UNIX,SOCK_STREAM,0);
//绑定
struct sockaddr_un clie;
bzero(&clie, sizeof(clie));//类似于memset
clie.sun_family = AF_UNIX;//同样使用AF_UNIX
strcpy(clie.sun_path, "./client.sock");//创建变量
int ret = bind(cfd, (struct sockaddr*)&clie, sizeof(clie));//绑定
if (ret < 0)
{
perror("bind error");
return -1;
}
int data[100];
int n;
//监听
ret = listen(cfd, 123);
if (ret < 0) {
perror("error");
exit(0);
}
struct sockaddr_un serv;//用于记录服务端地址
bzero(&serv, sizeof(serv));//类似于memset
serv.sun_family = AF_UNIX; //同样使用AF_UNIX
strcpy(serv.sun_path,"./server.sock");//创建变量
//连接
ret = connect(cfd,(struct sockaddr *)&serv,sizeof(serv));
if (ret < 0) {
perror("error");
exit(0);
}
while (1) {
memser(data,0x00,sizeof(data));//初始化
printf("请输入你要发送的数据\n");
scanf("%s", &data);
if (send(cfd, data, sizeof(data), 0) == -1) {
printf("发送数据失败\n");
return -1;
}
n = recv(cfd,data,sizeof(data),0);
printf("%s\n",data);
}
close(cfd);
}