本地套接字顾名思义就是用于本地通信的套接字,虽然网络套接字也能用于本地通信(通过本地回环测试127.0.0.1),但是还是需要绑定IP地址和端口号,这就没有本地套接字通信那么简便了。但是需要注意的事在客户端需要建立两个地址结构, 一个是定义自己的,一个是标注目的服务端的,而且是绝对路径,这样在服务端接收数据的时候就知道是哪个客户端伪文件传来的,不然的话打印不出来绝对路径。bind创建出来的文件就是伪文件(套接字文件),这个文件的大小是0,可以说就是一个棋子。
/虽然在很多教材中经常把Unix本地套接字放在网络编程里面进行讲解,但实际上,这种通信方式更类似于我们之前所学的IPC(进程间通信)的方式,比如无名管道(pipe)、有名管道(mkfifo)。但是,Unix域套接字所提供的控制方式会更多一些,比如说TCP(字节流套接字)提供等待连接的功能,UDP(数据报套接字)提供帧同步功能,同时也是全双工的(比如使用 socketpair 创建的流管道中的两个描述符都是既可读又可写的)。/转载一段文字
TCP服务端代码:
/*************************************************************************
> File Name: tcp_server.c
> Author: chencj
> Mail: 1378755306@qq.com
> Created Time: 2020年08月15日 星期六 14时58分47秒
************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#define FILE_PATH "/tmp/server.txt" //最好用绝对路径
void sys_err(const char *msg)
{
perror(msg);
exit(1);
}
int main()
{
int lfd,cfd;
char buf[128];
lfd = socket(AF_LOCAL,SOCK_STREAM,0);
if(lfd == -1)
sys_err("socket error\n");
struct sockaddr_un server_addr,client_addr; //地址结构
server_addr.sun_family = AF_LOCAL;
strcpy(server_addr.sun_path,FILE_PATH);
unlink(FILE_PATH);
//bind会在绝对路径下创建一个套接字伪文件,创建之前清除该文件
if(bind(lfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1)
sys_err("bind error\n");
if(listen(lfd,128) == -1)
sys_err("listen error\n");
//只与一个客户端进行通信
socklen_t len = sizeof(client_addr);
cfd = accept(lfd,(struct sockaddr*)&client_addr,&len);
if(cfd == -1)
sys_err("accept error\n");
while(1)
{
bzero(buf,sizeof(buf));
int recvb = read(cfd,buf,sizeof(buf));
if(recvb == 0) {
printf("client disconnect...\n");
close(cfd);
break;
}
printf("file path %s : %s\n",client_addr.sun_path,buf);
write(cfd,"accept",7);
}
close(lfd);
return 0;
}
TCP客户端代码:
/*************************************************************************
> File Name: tcp_client.c
> Author: chencj
> Mail: 1378755306@qq.com
> Created Time: 2020年08月15日 星期六 15时14分36秒
************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#define CLI_FILE_PATH "/tmp/client.txt"
#define SRV_FILE_PAYH "/tmp/server.txt"
void sys_err(const char *msg)
{
perror(msg);
exit(1);
}
int main()
{
char buf[128];
int sockfd;
sockfd = socket(AF_LOCAL,SOCK_STREAM,0);
if(sockfd == -1)
sys_err("socket error\n");
struct sockaddr_un server_addr,client_addr;
client_addr.sun_family = AF_LOCAL;
strcpy(client_addr.sun_path,CLI_FILE_PATH);
//不能像网络套接字那样隐式绑定
//客户端也要建立一个套接字伪文件,这样服务器在接受数据的时候才知道是本地的哪个路径下发来的
unlink(CLI_FILE_PATH);
bind(sockfd,(struct sockaddr*)&client_addr,sizeof(client_addr));
//目的服务器的地址结构
server_addr.sun_family = AF_LOCAL;
strcpy(server_addr.sun_path,SRV_FILE_PAYH);
//connect;
if(connect(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1) //与目的服务器进行连接
sys_err("connect error\n");
bzero(buf,sizeof(buf));
while(fgets(buf,128,stdin) != NULL)
{
write(sockfd,buf,sizeof(buf));
bzero(buf,sizeof(buf));
read(sockfd,buf,sizeof(buf));
printf("recv from server : %s\n",buf);
bzero(buf,sizeof(buf));
}
close(sockfd);
return 0;
}
UDP服务端代码:
/*************************************************************************
> File Name: tcp_server.c
> Author: chencj
> Mail: 1378755306@qq.com
> Created Time: 2020年08月15日 星期六 14时58分47秒
************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <sys/types.h>
#define FILE_PATH "/tmp/server.txt" //最好用绝对路径
void sys_err(const char *msg)
{
perror(msg);
exit(1);
}
int main()
{
int sockfd;
char buf[128];
sockfd = socket(AF_LOCAL,SOCK_DGRAM,0);
if(sockfd == -1)
sys_err("socket error\n");
struct sockaddr_un server_addr,client_addr; //地址结构
bzero(&client_addr,sizeof(client_addr));
server_addr.sun_family = AF_LOCAL;
strcpy(server_addr.sun_path,FILE_PATH);
unlink(FILE_PATH);
//bind会在绝对路径下创建一个套接字伪文件,创建之前清除该文件
if(bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1)
sys_err("bind error\n");
socklen_t len = sizeof(client_addr);
while(1)
{
bzero(buf,sizeof(buf));
int recvb;
recvb = recvfrom(sockfd,buf,128,0,(struct sockaddr *)&client_addr,&len);
if(recvb == -1)
sys_err("recvfrom error\n");
printf("file path %s : %s\n",client_addr.sun_path,buf);
sendto(sockfd,"accept",128,0,(struct sockaddr *)&client_addr,len);
}
close(sockfd);
return 0;
}
UDP客户端代码:
/*************************************************************************
> File Name: tcp_client.c
> Author: chencj
> Mail: 1378755306@qq.com
> Created Time: 2020年08月15日 星期六 15时14分36秒
************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <sys/types.h>
#define CLI_FILE_PATH "/tmp/client.txt"
#define SRV_FILE_PAYH "/tmp/server.txt"
void sys_err(const char *msg)
{
perror(msg);
exit(1);
}
int main()
{
char buf[128];
int sockfd;
sockfd = socket(AF_LOCAL,SOCK_DGRAM,0);
if(sockfd == -1)
sys_err("socket error\n");
struct sockaddr_un server_addr,client_addr;
client_addr.sun_family = AF_LOCAL;
strcpy(client_addr.sun_path,CLI_FILE_PATH);
//不能像网络套接字那样隐式绑定
//客户端也要建立一个套接字伪文件,这样服务器在接受数据的时候才知道是本地的哪个路径下发来的
unlink(CLI_FILE_PATH);
bind(sockfd,(struct sockaddr*)&client_addr,sizeof(client_addr));
//目的服务器的地址结构
server_addr.sun_family = AF_LOCAL;
strcpy(server_addr.sun_path,SRV_FILE_PAYH);
bzero(buf,sizeof(buf));
struct sockaddr_un recvaddr;
socklen_t len = sizeof(recvaddr);
bzero(&recvaddr,len);
while(fgets(buf,128,stdin) != NULL)
{
sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&server_addr,sizeof(server_addr));
bzero(buf,sizeof(buf));
recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&recvaddr,&len);
printf("recvform server : %s\n",buf);
bzero(buf,sizeof(buf));
}
close(sockfd);
return 0;
}