Linux网络编程day8本地套接字
本地套接字
利用cs模型实现本地套接字完成进程间通信
对比网络编程TCP C/S模型,注意以下几点
1、int socket(int domain, int type, int protocol); domain-->AF_INET改为AF_UNIX ,
type都可写SOCK_STREAM/SOCK_DGRAM2、地址结构 sockaddr_in -->sockaddr_unstruct sockaddr_un serv_addr;serv_addr.sun_family = AF_UNIXstrcpy(serv_addr.sun_path , "serv.socket")len = offsetof(struct sockaddr_un , sun_path) + strlen("serv.socket")
offsetof(struct sockaddr_un , sun_path)求出来就是2,首地址偏移3、bind(sockfd , (struct sockaddr*) &serv_addr , len);
bind()函数调用成功,会创建一个sockfd,因此为了保证bind成功,通常在bind之前使用unlink("serv.socket");4、客户端不能依赖隐式绑定,并且应该在通信建立过程中,初始化2个地址结构
1)、client_addr--->bind()
2)、serv_addr--->connect()
本地套接字实现进程间通信服务器模型
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/un.h>
#include<ctype.h>
#include<stddef.h>
#define SERV_ADDR "serv.socket"
int main(int argc , char *argv[])
{struct sockaddr_un serv_addr , clit_addr;int sockfd , cfd;char buf[BUFSIZ];int i , n , len;sockfd = socket(AF_UNIX , SOCK_STREAM , 0);serv_addr.sun_family = AF_UNIX;strcpy(serv_addr.sun_path , SERV_ADDR);len = offsetof(struct sockaddr_un , sun_path) + strlen(SERV_ADDR);unlink(SERV_ADDR);bind(sockfd , (struct sockaddr*)&serv_addr , len);listen(sockfd , 128);printf("Accepting connections....\n");while(1){len = sizeof(clit_addr);cfd = accept(sockfd , (struct sockaddr*)&clit_addr , (socklen_t*)&len);len -= offsetof(struct sockaddr_un , sun_path);clit_addr.sun_path[len] = '\0';printf("client bind filename %s\n" , clit_addr.sun_path);while((n = read(cfd , buf , sizeof(buf)))>0){if(n > 0){for(i = 0 ; i < n ; i++)buf[i] = toupper(buf[i]);}write(cfd , buf , n);write(STDOUT_FILENO , buf , n);}}close(sockfd);return 0 ;
}
本地套接字实现进程间通信客户端模型
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/un.h>
#include<stddef.h>
#define SERV_PORT 9004#define SERV_ADDR "serv.socket"
#define CLIT_ADDR "clit.socket"void sys_err(char*s)
{perror(s);exit(1);
}int main(int argc , char *argv[])
{int n , ret , cfd , len;char buf[BUFSIZ];struct sockaddr_un serv_addr , clit_addr;cfd = socket(AF_UNIX , SOCK_STREAM , 0);clit_addr.sun_family = AF_UNIX;strcpy(clit_addr.sun_path , CLIT_ADDR);len = offsetof(struct sockaddr_un , sun_path) + strlen(CLIT_ADDR);unlink(CLIT_ADDR);ret = bind(cfd , (struct sockaddr*)&clit_addr , len);if(ret == -1)sys_err("bind error");serv_addr.sun_family = AF_UNIX;strcpy(serv_addr.sun_path , SERV_ADDR);len = offsetof(struct sockaddr_un , sun_path) + strlen(SERV_ADDR);if((connect(cfd , (struct sockaddr*)&serv_addr , (socklen_t)len))== -1)sys_err("connect error");while(fgets(buf , sizeof(buf) , stdin) != NULL ){n = write(cfd , buf , strlen(buf));if(n == -1)sys_err("write error");len = read(cfd , buf , (sizeof(buf)));if(n == -1)sys_err("read error");write(STDOUT_FILENO , buf , len);}close(cfd);return 0 ;
}
这里要注意其和网络通信中的区别,在客户端中不仅要绑定且初始化自己的地址结构,也要初始化服务器端的地址结构,不能依赖隐式绑定。
还需要注意,在这个模型中bind之前都需要进行unlink操作。