socket 模式.docx
- 文档编号:6080296
- 上传时间:2023-01-03
- 格式:DOCX
- 页数:11
- 大小:17.93KB
socket 模式.docx
《socket 模式.docx》由会员分享,可在线阅读,更多相关《socket 模式.docx(11页珍藏版)》请在冰豆网上搜索。
socket模式
三、异步阻塞模式
另外一个阻塞解决方案是带有阻塞通知的非阻塞I/O。
在这种模型中,配置的是非阻塞I/O,然后使用阻塞select系统调用来确定一个I/O描述符何时有操作。
使select调用非常有趣的是它可以用来为多个描述符提供通知,而不仅仅为一个描述符提供通知。
对于每个提示符来说,我们可以请求这个描述符可以写数据、有读数据可用以及是否发生错误的通知
下面的C语言实现的例子,它从网络上接受数据写入一个文件中:
/*
*\brief
*tcpclient
*/
1.#include
2.#include
3.#include
4.#include
5.#include
6.#include
7.#include
8.
9.#include
10.#include
11.#include
#defineSERVPORT8080
#defineMAXDATASIZE100
#defineTFILE"data_from_socket.txt"
intmain(intargc,char*argv[])
{
intsockfd,recvbytes;
charrcv_buf[MAXDATASIZE];/*./client127.0.0.1hello*/
charsnd_buf[MAXDATASIZE];
structhostent*host; /*structhostent
*{
*char*h_name;//generalhostname
*char**h_aliases;//hostname'salias
*inth_addrtype;//AF_INET
*inth_length;
*char**h_addr_list;
*};
*/
structsockaddr_inserver_addr;
/**/
fd_setreadset,writeset;
intcheck_timeval=1;
structtimevaltimeout={check_timeval,0};//阻塞式select,等待1秒,1秒轮询
intmaxfd;
intfp;
intcir_count=0;
intret;
if(argc<3)
{
printf("Usage:
%s[ipaddress][anystring]\n",argv[0]);
return1;
}
*snd_buf='\0';
strcat(snd_buf,argv[2]);
if((fp=open(TFILE,O_WRONLY))<0) //不是用fopen
{
perror("fopen:
");
exit
(1);
}
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket:
");
exit
(1);
}
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(SERVPORT);
inet_pton(AF_INET,argv[1],&server_addr.sin_addr);
memset(&(server_addr.sin_zero),0,8);
/*createtheconnectionbysocket
*meansthatconnect"sockfd"to"server_addr"
*/
if(connect(sockfd,(structsockaddr*)&server_addr,sizeof(structsockaddr))==-1)
{
perror("connect");
exit
(1);
}
/**/
if(send(sockfd,snd_buf,sizeof(snd_buf),0)==-1)
{
perror("send:
");
exit
(1);
}
printf("send:
%s\n",snd_buf);
while
(1)
{
FD_ZERO(&readset); //每次循环都要清空集合,否则不能检测描述符变化
FD_SET(sockfd,&readset); //添加描述符
FD_ZERO(&writeset);
FD_SET(fp, &writeset);
maxfd=sockfd>fp?
(sockfd+1):
(fp+1); //描述符最大值加1
ret=select(maxfd,&readset,NULL,NULL,NULL); //阻塞模式
switch(ret)
{
case-1:
exit(-1);
break;
case0:
break;
default:
if(FD_ISSET(sockfd,&readset)) //测试sock是否可读,即是否网络上有数据
{
recvbytes=recv(sockfd,rcv_buf,MAXDATASIZE,MSG_DONTWAIT);
rcv_buf[recvbytes]='\0';
printf("recv:
%s\n",rcv_buf);
if(FD_ISSET(fp,&writeset))
{
write(fp,rcv_buf,strlen(rcv_buf)); //不是用fwrite
}
gotoend;
}
}
cir_count++;
printf("CNT:
%d\n",cir_count);
}
end:
close(fp);
close(sockfd);
return0;
}
perl实现:
#!
/usr/bin/perl
###############################################################################
#\File
# tcp_client.pl
#\Descript
# sendmessagetoserver
###############################################################################
useIO:
:
Socket;
useIO:
:
Select;
#hashtoinstallIPPort
%srv_info=(
#"srv_ip" =>"61.184.93.197",
"srv_ip" =>"192.168.1.73",
"srv_port"=>"8080",
);
my$srv_addr=$srv_info{"srv_ip"};
my$srv_port=$srv_info{"srv_port"};
my$sock=IO:
:
Socket:
:
INET->new(
PeerAddr=>"$srv_addr",
PeerPort=>"$srv_port",
Type =>SOCK_STREAM,
Blocking=>1,
# Timeout =>5,
Proto =>"tcp")
ordie"Cannotcreatesocketconnect.$@";
$sock->send("Helloserver!
\n",0)orwarn"sendfailed:
$!
$@";
$sock->autoflush
(1);
my$sel=IO:
:
Select->new($sock);
while(my@ready=$sel->can_read)
{
foreachmy$fh(@ready)
{
if($fh==$sock)
{
while()
{
print$_;
}
$sel->remove($fh);
close$fh;
}
}
}
$sock->close();
四、异步非阻塞模式
最后,异步非阻塞I/O模型是一种处理与I/O重叠(并行)进行的模型。
以read系统调用为例
steps:
a.调用read;
b.read请求会立即返回,说明请求已经成功发起了。
c.在后台完成读操作这段时间内,应用程序可以执行其他处理操作。
d.当read的响应到达时,就会产生一个信号或执行一个基于线程的回调函数来完成这次I/O处理过程。
/*
*\brief
*tcpclient
*/
1.#include
2.#include
3.#include
4.#include
5.#include
6.#include
7.#include
8.
9.#include
10.#include
11.#include
#defineSERVPORT8080
#defineMAXDATASIZE100
#defineTFILE"data_from_socket.txt"
intmain(intargc,char*argv[])
{
intsockfd,recvbytes;
charrcv_buf[MAXDATASIZE];/*./client127.0.0.1hello*/
charsnd_buf[MAXDATASIZE];
structhostent*host; /*structhostent
*{
*char*h_name;//generalhostname
*char**h_aliases;//hostname'salias
*inth_addrtype;//AF_INET
*inth_length;
*char**h_addr_list;
*};
*/
structsockaddr_inserver_addr;
/**/
fd_setreadset,writeset;
intcheck_timeval=1;
structtimevaltimeout={check_timeval,0};//阻塞式select,等待1秒,1秒轮询
intmaxfd;
intfp;
intcir_count=0;
intret;
if(argc<3)
{
printf("Usage:
%s[ipaddress][anystring]\n",argv[0]);
return1;
}
*snd_buf='\0';
strcat(snd_buf,argv[2]);
if((fp=open(TFILE,O_WRONLY))<0) //不是用fopen
{
perror("fopen:
");
exit
(1);
}
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket:
");
exit
(1);
}
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(SERVPORT);
inet_pton(AF_INET,argv[1],&server_addr.sin_addr);
memset(&(server_addr.sin_zero),0,8);
/*createtheconnectionbysocket
*meansthatconnect"sockfd"to"server_addr"
*/
if(connect(sockfd,(structsockaddr*)&server_addr,sizeof(structsockaddr))==-1)
{
perror("connect");
exit
(1);
}
/**/
if(send(sockfd,snd_buf,sizeof(snd_buf),0)==-1)
{
perror("send:
");
exit
(1);
}
printf("send:
%s\n",snd_buf);
while
(1)
{
FD_ZERO(&readset); //每次循环都要清空集合,否则不能检测描述符变化
FD_SET(sockfd,&readset); //添加描述符
FD_ZERO(&writeset);
FD_SET(fp, &writeset);
maxfd=sockfd>fp?
(sockfd+1):
(fp+1); //描述符最大值加1
ret=select(maxfd,&readset,NULL,NULL, &timeout); //非阻塞模式
switch(ret)
{
case-1:
exit(-1);
break;
case0:
break;
default:
if(FD_ISSET(sockfd,&readset)) //测试sock是否可读,即是否网络上有数据
{
recvbytes=recv(sockfd,rcv_buf,MAXDATASIZE,MSG_DONTWAIT);
rcv_buf[recvbytes]='\0';
printf("recv:
%s\n",rcv_buf);
if(FD_ISSET(fp,&writeset))
{
write(fp,rcv_buf,strlen(rcv_buf)); //不是用fwrite
}
gotoend;
}
}
timeout.tv_sec=check_timeval; //必须重新设置,因为超时时间到后会将其置零
cir_count++;
printf("CNT:
%d\n",cir_count);
}
end:
close(fp);
close(sockfd);
return0;
}
五、server端程序:
/*
*\brief
*tcpserver
*/
1.#include
2.#include
3.#include
4.#include
5.#include
6.#include
7.#include
#defineSERVPORT8080
#defineBACKLOG10//maxnumbefofclientconnection
#defineMAXDATASIZE100
intmain(charargc,char*argv[])
{
intsockfd,client_fd,addr_size,recvbytes;
charrcv_buf[MAXDATASIZE],snd_buf[MAXDATASIZE];
char*val;
structsockaddr_inserver_addr;
structsockaddr_inclient_addr;
intbReuseaddr=1;
charIPdotdec[20];
/*createanewsocketandregiterittoos.
*SOCK_STREAMmeansthatsupplytcpservice,
*andmustconnect()beforedatatransfort.
*/
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket:
");
exit
(1);
}
/*settingserver'ssocket*/
server_addr.sin_family=AF_INET; //IPv4networkprotocol
server_addr.sin_port=htons(SERVPORT);
server_addr.sin_addr.s_addr=INADDR_ANY;//autoIPdetect
memset(&(server_addr.sin_zero),0,8);
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(constchar*)&bReuseaddr,sizeof(int));
if(bind(sockfd,(structsockaddr*)&server_addr,sizeof(structsockaddr))==-1)
{
perror("bind:
");
exit
(1);
}
/*
*wattingforconnection,
*andserverpermittorecivetherequestionfromsockfd
*/
if(listen(sockfd,BACKLOG)==-1)//BACKLOGassignthdmaxnumberofconnection
{
perror("listen:
");
exit
(1);
}
while
(1)
{
addr_size=
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- socket 模式
![提示](https://static.bdocx.com/images/bang_tan.gif)