你知道linux socket进程通信是怎样实现的?

socket进程通信与网络通信使用的是统一套接口,只是地址结构与某些参数不同。
一。创建socket服务端的流程如下:
(1)创建socket,类型为af_local或af_unix,表示用于进程通信:
[cpp]view plaincopy
intserver_fd;
intclient_fd;//clientfiledescriptor
structsockaddr_unserver_addr;
structsockaddr_unclient_addr;
size_tserver_len,client_len;
//cteateserversocket
//deleteoldsocketfile
unlink(server_name);
if((server_fd=socket(af_unix,sock_stream,0))==-1){
perror(socket);
exit(1);
}
(2)命名socket。这里面有一个很关键的东西,socket进程通信命名方式有两种。一是普通的命名,socket会根据此命名创建一个同名的socket文件,客户端连接的时候通过读取该socket文件连接到socket服务端。这种方式的弊端是服务端必须对socket文件的路径具备写权限,客户端必须知道socket文件路径,且必须对该路径有读权限。另外一种命名方式是抽象命名空间,这种方式不需要创建socket文件,只需要命名一个全局名字,即可让客户端根据此名字进行连接。后者的实现过程与前者的差别是,后者在对地址结构成员sun_path数组赋值的时候,必须把第一个字节置0,即sun_path[0] = 0,下面用代码说明:
第一种方式:
[cpp]view plaincopy
//nametheserversocket
server_addr.sun_family=af_unix;
strcpy(server_addr.sun_path,server_name);
server_len=sizeof(structsockaddr_un);
client_len=server_len;
第二种方式:
[cpp]view plaincopy
//namethesocket
server_addr.sun_family=af_unix;
strcpy(server_addr.sun_path,server_name);
server_addr.sun_path[0]=0;
//server_len=sizeof(server_addr);
server_len=strlen(server_name)+offsetof(structsockaddr_un,sun_path);
其中,offsetof函数在#include 头文件中定义。因第二种方式的首字节置0,我们可以在命名字符串server_name前添加一个占位字符串,例如:
[cpp]view plaincopy
#defineserver_name@socket_server
前面的@符号就表示占位符,不算为实际名称。
或者可以把第二种方式的实现封装成一个函数:
[cpp]view plaincopy
intmakeaddr(constchar*name,structsockaddr_un*paddr,socklen_t*psocklen)
{
intnamelen=strlen(name);
if(namelen>=(int)sizeof(paddr->sun_path)-1)/*toolong?*/
return-1;
paddr->sun_path[0]='\0';/*abstractnamespace*/
strcpy(paddr->sun_path+1,name);
paddr->sun_family=af_unix;
*psocklen=1+namelen+offsetof(structsockaddr_un,sun_path);
return0;
}
像下面这样使用这个函数:
[cpp]view plaincopy
makeaddr(server_socket,&server_addr,&server_len);
提示:客户端连接服务器的时候,必须与服务端的命名方式相同,即如果服务端是普通命名方式,客户端的地址也必须是普通命名方式;如果服务端是抽象命名方式,客户端的地址也必须是抽象命名方式。
(3)绑定并侦听
[cpp]view plaincopy
bind(server_sockfd,(structsockaddr*)&server_addr,server_len);
//listentheserver
listen(server_sockfd,5);
(4)等待客户端连接,并读写数据。
[cpp]view plaincopy
while(1){
printf(serverwaiting...\n);
//acceptclientconnect
client_len=sizeof(client_addr);
client_sockfd=accept(server_sockfd,(structsockaddr*)&client_addr,&client_len);
//readdatafromclientsocket
read(client_sockfd,&ch,1);
printf(readfromclient%d:%c,client_sockfd,ch);
ch++;
write(client_sockfd,&ch,1);
close(client_sockfd);
usleep(100);//1000miliseconds=1second
}
二 socket客户端创建流程
(1)创建socket
(2)命名socket
(3)连接到服务端:
[cpp]view plaincopy
//connecttoserver
result=connect(sockfd,(structsockaddr*)&address,len);
(4)与服务端进行通信
[cpp]view plaincopy
//communicatewithserversocket
while(1)
{
printf(setsendcontent:);
scanf(%c,&ch);
write(sockfd,&ch,1);
printf(sendtoserver:%c\n,ch);
read(sockfd,&ch,1);
printf(readfromserver:%c\n,ch);
}
完整代码如下:
(1)服务端server.c:
[cpp]view plaincopy
#include
#include
#include
#include
#include
#include
#include
#defineserver_name@server_socket
/*
*createaunix-domainsocketaddressinthelinuxabstractnamespace.
*
*thesocketcodedoesn'trequirenullterminationonthefilename,but
*wedoitanywaysostringfunctionswork.
*/
intmakeaddr(constchar*name,structsockaddr_un*paddr,socklen_t*psocklen)
{
intnamelen=strlen(name);
if(namelen>=(int)sizeof(paddr->sun_path)-1)/*toolong?*/
return-1;
paddr->sun_path[0]='\0';/*abstractnamespace*/
strcpy(paddr->sun_path+1,name);
paddr->sun_family=af_unix;
*psocklen=1+namelen+offsetof(structsockaddr_un,sun_path);
return0;
}
intmain()
{
intserver_sockfd,client_sockfd;
socklen_tserver_len,client_len;
structsockaddr_unserver_addr;
structsockaddr_unclient_addr;
charch;
intnread;
//deletetheoldserversocket
//unlink(server_socket);
//createsocket
server_sockfd=socket(af_unix,sock_stream,0);
//namethesocket
server_addr.sun_family=af_unix;
strcpy(server_addr.sun_path,server_name);
server_addr.sun_path[0]=0;
//server_len=sizeof(server_addr);
server_len=strlen(server_name)+offsetof(structsockaddr_un,sun_path);
//makeaddr(server_socket,&server_addr,&server_len);
bind(server_sockfd,(structsockaddr*)&server_addr,server_len);
//listentheserver
listen(server_sockfd,5);
client_sockfd=-1;
client_len=sizeof(client_addr);
while(1){
printf(serverwaiting...\n);
//acceptclientconnect
if(client_sockfd==-1){
client_sockfd=accept(server_sockfd,(structsockaddr*)&client_addr,&client_len);
}
//readdatafromclientsocket
nread=read(client_sockfd,&ch,1);
if(nread==0){//clientdisconnected
printf(client%ddisconnected\n,client_sockfd);
client_sockfd=-1;
}
else{
printf(readfromclient%d:%c\n,client_sockfd,ch);
ch++;
write(client_sockfd,&ch,1);
}
usleep(100);//1000miliseconds=1second
}
return0;
}
(2)客户端client.c
[cpp]view plaincopy
#include
#include
#include
#include
#include
#include
#include
#defineserver_name@server_socket
/*
*createaunix-domainsocketaddressinthelinuxabstractnamespace.
*
*thesocketcodedoesn'trequirenullterminationonthefilename,but
*wedoitanywaysostringfunctionswork.
*/
intmakeaddr(constchar*name,structsockaddr_un*paddr,socklen_t*psocklen)
{
intnamelen=strlen(name);
if(namelen>=(int)sizeof(paddr->sun_path)-1)/*toolong?*/
return-1;
paddr->sun_path[0]='\0';/*abstractnamespace*/
strcpy(paddr->sun_path+1,name);
paddr->sun_family=af_unix;
*psocklen=1+namelen+offsetof(structsockaddr_un,sun_path);
return0;
}
intmain()
{
intsockfd;
socklen_tlen;
structsockaddr_unaddress;
intresult;
charch='a';
//createsocket
sockfd=socket(af_unix,sock_stream,0);
//nametheserversocket
//makeaddr(server_socket,&address,&len);
address.sun_family=af_unix;
strcpy(address.sun_path,server_name);
address.sun_path[0]=0;
//len=sizeof(address);
len=strlen(server_name)+offsetof(structsockaddr_un,sun_path);
//connecttoserver
result=connect(sockfd,(structsockaddr*)&address,len);
if(result==-1)
{
perror(opps:client1);
exit(1);
}
//communicatewithserversocket
while(1)
{
printf(setsendcontent:);
scanf(%c,&ch);
write(sockfd,&ch,1);
printf(sendtoserver:%c\n,ch);
read(sockfd,&ch,1);
printf(readfromserver:%c\n,ch);
}
exit(0);
}

ac/dc电源转换电路包括哪些环节?
年度评价最高的VR游戏!这款游戏究竟有什么魅力呢?
清华人工智能研究院成立,与谷歌、腾讯展开AI合作服务国家重大战略
Snapchat推出具有增强现实功能的相机效果,可激发社交距离
小米POCO X2今日在印度首售,搭载液冷散热模块
你知道linux socket进程通信是怎样实现的?
插入式测温仪适用于哪些场所进行温度检测
双核三防机松下Eluga正式开卖
开关管的工作原理 开关管怎么检测好坏
不伤耳膜的耳机哪种好,保护听力的耳机品牌
如果三极管断了一个引脚能否当二极管使用?
兼容各家标准的chaoji充电标准如何设计
我们需要哪些改变来支持更高的数据速率
硅基集成光量子芯片技术解析
大胆猜想:子弹短信如何用增长黑客攻击微信
!售`S331C、S331C驻波比测试仪S331C 小兵/何
电源管理厂商龙争虎斗 德州仪器独占鳌头
Arm全新汽车图像信号处理器 加速驾驶辅助与自动化技术的导入
UPS电源的发展趋势
max232电平转换电路及原理