本地套接字与网络套接字的区别:
1.网络套接字是通过绑定ip和端口使网络中的进程之间进行通信,而本地套接字是绑定套接字文件的路径名来使单机中的进程间通信,是一种IPC机制,其存储地址结构的数据类型为struct sockaddr_un,该数据类型包含在#include
头文件中
#define UNIX_PATH_MAX 108
struct sockaddr_un {
sa_family_t sun_family; /*PF_UNIX或AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* 路径名 */
};
2.网络套接字客户端可以隐式绑定ip和端口,但是本地套接字客户端必须绑定套接字文件的路径名,否则无法通信(因为本地套接字通信模式中bind函数会创建套接字文件,两个进程之间的通信是通过各自的套接字文件来进行的)
除了以上两点外,本地套接字通信模式与网络套接字基本相同,我们可以直接看代码:
TCP(字节流套接字)
server.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PATH "serv_sock_file"
int main(void)
{
int lfd,len,cfd,ret;
char buf[BUFSIZ];
struct sockaddr_un serv_addr,clie_addr;
socklen_t clie_addr_len = sizeof(clie_addr);
//绑定地址结构
serv_addr.sun_family = AF_UNIX;
strcpy(serv_addr.sun_path,SERVER_PATH);
lfd = socket(AF_UNIX,SOCK_STREAM,0);//建立本地套接字 AF_UNIX参数代表创建的是本地套接字
if(lfd == -1)
{
perror("socket error");
exit(1);
}
len = offsetof(struct sockaddr_un,sun_path) + strlen(serv_addr.sun_path);//获取serv_addr实际存储数据的长度
unlink(SERVER_PATH);//若文件存在则删除文件,防止bind创建文件失败
ret = bind(lfd,(struct sockaddr*)&serv_addr,len);//绑定地址结构并创建套接字文件
if(ret == -1)
{
perror("bind error");
exit(1);
}
listen(lfd,128);
while(1)
{
cfd = accept(lfd,(struct sockaddr*)&clie_addr,&clie_addr_len);
if(cfd == -1)
{
perror("accept error");
exit(1);
}
while(1)
{
int n = read(cfd,buf,sizeof(buf));
if(n == -1)
{
perror("read error");
exit(1);
}
else if(n == 0)
{
close(cfd);
break;
}
for(int i = 0;i < n;i++)
buf[i] = toupper(buf[i]);
write(cfd,buf,n);
}
}
close(lfd);
return 0;
}
client.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PATH "serv_sock_file"
#define CLIENT_PATH "clie_sock_file"
int main(void)
{
int cfd,len,ret;
char buf[BUFSIZ];
struct sockaddr_un ser_addr,cli_addr;
cli_addr.sun_family = AF_UNIX;
strcpy(cli_addr.sun_path,CLIENT_PATH);
cfd = socket(AF_UNIX,SOCK_STREAM,0);
len = offsetof(struct sockaddr_un,sun_path) + strlen(cli_addr.sun_path);
unlink(CLIENT_PATH);
bind(cfd,(struct sockaddr*)&cli_addr,(socklen_t)len);
ser_addr.sun_family = AF_UNIX;
strcpy(ser_addr.sun_path,SERVER_PATH);
len = offsetof(struct sockaddr_un,sun_path) + strlen(ser_addr.sun_path);
ret = connect(cfd,(struct sockaddr*)&ser_addr,len);
if(ret == -1)
{
perror("connect error");
exit(1);
}
while(fgets(buf,sizeof(buf),stdin) != NULL)
{
write(cfd,buf,strlen(buf));
int n = read(cfd, buf,sizeof(buf));
if(n == -1)
{
perror("read error");
exit(1);
}
else if(n == 0)
break;
write(STDOUT_FILENO,buf,n);
}
close(cfd);
return 0;
}
UDP(数据报套接字)
server.c
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PATH "serv_sock_file"
int main(void)
{
int sockfd,len;
char buf[BUFSIZ];
struct sockaddr_un ser_addr,cli_addr;
socklen_t cli_addr_len = sizeof(cli_addr);
sockfd = socket(AF_UNIX,SOCK_DGRAM,0);
ser_addr.sun_family = AF_UNIX;
strcpy(ser_addr.sun_path,SERVER_PATH);
unlink(SERVER_PATH);
len = offsetof(struct sockaddr_un,sun_path) + strlen(ser_addr.sun_path);
bind(sockfd,(struct sockaddr*)&ser_addr,len);
while(1)
{
int n = recvfrom(sockfd,buf,sizeof(buf),0,(struct
sockaddr*)&cli_addr,&cli_addr_len);
if(n == -1)
{
perror("recvfrom error");
exit(1);
}
for(int i = 0; i < n ;i++)
buf[i] = toupper(buf[i]);
sendto(sockfd,buf,n,0,(struct sockaddr*)&cli_addr,sizeof(cli_addr));
}
close(sockfd);
return 0;
}
client.c
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PATH "serv_sock_file"
#define CLIENT_PATH "clie_sock_file"
int main(void)
{
int sockfd,len;
char buf[BUFSIZ];
struct sockaddr_un ser_addr,cli_addr;
sockfd = socket(AF_UNIX,SOCK_DGRAM,0);
cli_addr.sun_family = AF_UNIX;
strcpy(cli_addr.sun_path,CLIENT_PATH);
unlink(CLIENT_PATH);
len = offsetof(struct sockaddr_un,sun_path) + strlen(cli_addr.sun_path);
bind(sockfd,(struct sockaddr*)&cli_addr,len);
ser_addr.sun_family = AF_UNIX;
strcpy(ser_addr.sun_path,SERVER_PATH);
len = offsetof(struct sockaddr_un,sun_path) + strlen(ser_addr.sun_path);
while(fgets(buf,sizeof(buf),stdin) != NULL)
{
sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&ser_addr,len);
recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL);
write(STDOUT_FILENO,buf,strlen(buf));
}
close(sockfd);
return 0;
}