揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx

上传人:b****1 文档编号:5679973 上传时间:2023-05-05 格式:DOCX 页数:29 大小:53.79KB
下载 相关 举报
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第1页
第1页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第2页
第2页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第3页
第3页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第4页
第4页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第5页
第5页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第6页
第6页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第7页
第7页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第8页
第8页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第9页
第9页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第10页
第10页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第11页
第11页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第12页
第12页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第13页
第13页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第14页
第14页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第15页
第15页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第16页
第16页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第17页
第17页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第18页
第18页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第19页
第19页 / 共29页
揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx_第20页
第20页 / 共29页
亲,该文档总共29页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx

《揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx(29页珍藏版)》请在冰点文库上搜索。

揭开unix网络之纱1 客户服务器编程范式Word格式文档下载.docx

structtimevalru_stime;

/*systemtimeused*/

longru_maxrss;

/*maximumresidentsetsize*/

longru_ixrss;

/*integralsharedmemorysize*/

longru_idrss;

/*integralunshareddatasize*/

longru_isrss;

/*integralunsharedstacksize*/

longru_minflt;

/*pagereclaims*/

longru_majflt;

/*pagefaults*/

longru_nswap;

/*swaps*/

longru_inblock;

/*blockinputoperations*/

longru_oublock;

/*blockoutputoperations*/

longru_msgsnd;

/*messagessent*/

longru_msgrcv;

/*messagesreceived*/

longru_nsignals;

/*signalsreceived*/

longru_nvcsw;

/*voluntarycontextswitches*/

longru_nivcsw;

/*involuntarycontextswitches*/

};

RETURNVALUE

Onsuccess,zeroisreturned.Onerror,-1isreturned,anderrnoissetappropriately.

ERRORS

EFAULTusagepointsoutsidetheaccessibleaddressspace.

EINVALwhoisinvalid.

3.2Getaddrinfo函数和freeaddrinfo

getaddrinfo函数能够处理名字到地址以及服务到端口这两种转换,返回的是一个sockaddr结构而不是一个地址列表。

这些sockaddr结构随后可由套接字函数直接使用。

如此一来,getaddrinfo函数把协议相关性完全隐藏在这个库函数内部。

应用程序只需要处理由getaddrinfo填写套接字地址结构。

netdb.h>

intgetaddrinfo(constchar*hostname,constchar*service,conststructaddrinfo*hints,structaddrinfo**result);

本函数通过result指针参数返回一个指向addrinfo结构链表的指针,而addrinof结构定义在头文件<

中。

structaddrinfo{

intai_flags;

intai_family;

intai_socktype;

intai_protocol;

socklen_tai_addrlen;

char*ai_canonname;

structsockaddr*ai_addr;

structaddrinfo*ai_next;

};

其中hostname参数是一个主机名或地址串。

service参数是一个服务名或十进制端口号数串。

hints参数可以是一个空指针,也可以是一个指向某个addrinfo结构的指针,调用者在这个结构中填入关于期望返回的信息类型的暗示。

hints结构中调用者可以设置的成员有:

●ai_flags(零个或多个或在一起的AI_xxx值);

●ai_family(某个AF_xxx值)

●ai_socktype(某个SOCK_xxx值)

●ai_protocol

其中ai_flags成员可用的标志值及其含义如下:

AI_PASSIVE

套接字将用于被动打开

AI_CANONNAME

告知getaddrinfo函数返回主机的规范名字

AI_NUMERICHOST

防止任何类型的名字到地址映射,hostname参数必须是一个地址串

防止任何类型的名字到服务映射,service参数必须是一个十进制端口号数串

AI_VAMAPPED

如果同时指定ai_family成员的值为AF_INET6,那么如果没有可用的AAAA记录,就返回与A记录对应的IPv4映射的IPv6地址。

AI_ALL

如果同时指定AI_V4MAPPED标志,那么除了返回与AAAA记录对应的IPV6地址外,还返回与A记录对应的IPV4映射的IPV6地址

AI_ADDRCONFIG

按照所在主机的配置选择返回地址类型,也就是只查找与所在主机回馈接口以外的网络接口配置的IP地址版本一致的地址。

如果hints参数是一个空指针,本函数就假设ai_flag、ai_socktype和ai_protocol的值均为0,ai_family的值为AF_UNSPEC。

如果本函数返回成功(0),那么由result参数指向的变量已被填入一个指针,它指向的是有其中的ai_next成员串接起来的adrinfo结构链表。

可导致返回多个addrinfo结构的情形有一下两个。

1)如果与hostname参数关联的地址有多个,那么适用于所请求地址族(可通过hints结构的ai_family成员设置)的每个地址都返回一个对应的结构。

2)如果service参数指定的服务支持多个套接字类型,那么每个套接字类型都可能返回一个对应的结构,具体取决于hints结构的ai_socktype成员。

在addrinfo结构中返回的信息可现成用于socket调用,随后现成用于适合客户的connect或sendto调用,或者是适合服务器的bind调用。

Socket函数的参数就是addrinfo结构中的ai_family、ai_socktype和ai_addr成员。

Connect或bind函数的第二个和第三个参数就是该结构中的ai_addr和ai_addrlen成员。

如果在hints结构中设置了AI_CANONNAME标志,那么本函数返回的第一个addrinfo结构的ai_canoname成员指向所查找主机的规范名字。

按照DNS的说法,规范名字通常是FQDN。

诸如telnet之类程序往往使用这个标志以显示所连接到主机的规范名字,这样即使用户给定的是一个简单的名字或别名,他们也能搞清真正查找的名字。

使用freeaddrinfo释放result

4tcp客户端

为了省事,也是为了学习python,更是检查跨语言的数据传递,使用python

#!

/usr/bin/envpython

fromsocketimport*

HOST='

127.0.0.1'

PORT=55555

BUFSIZE=1024

ADDR=(HOST,PORT)

tcpCliSock=socket(AF_INET,SOCK_STREAM)

tcpCliSock.connect(ADDR)

whileTrue:

data=raw_input('

>

'

ifnotdata:

break

tcpCliSock.send(data)

data=tcpCliSock.recv(BUFSIZE)

printdata

tcpCliSock.close()

5公用函数

史蒂文的书比较困难的就是大量的交叉引用,要看一个章节就要上溯更多的资料,呜呼!

难啊!

所以先写和复习一点由史蒂文自己写的公共的函数。

5.1I/O函数

字节流套接字(例如Tcp套接字)上的read和write函数所表现的行为不同于通常的文件I/O。

字节流套接字上调用read或writen输入或输出的字节数可能比请求的数量少,然而这不是出错的状态。

这个现象的原因在于内核中用于套接字的缓冲区可能已到达了极限。

此时所需要的是调用者再次调用read或writen函数,以输入或输出剩余的字节。

有些版本的unix在往一个管道中写入4096字节的数据时也会表现出这样的行为。

这个现象在read一个字节流套接字时很常见,但是在Write一个字节流套接字时子女在套接字为非阻塞的前提下才出现。

尽管如此,为预防万一,不让实现返回一个不足的字节计数值,我们总是改为调用writen函数来取代write函数。

5.1.1readn函数

ssize_treadn(intfd,void*vptr,size_tn)

{

size_tnleft;

ssize_tnread;

char*ptr;

ptr=vptr;

nleft=n;

while(nleft>

0){

if((nread=read(fd,ptr,nleft))<

0)

{

if(errno==EINTR)

nread=0;

else

return-1;

}

elseif(nread==0)

break;

nleft-=nread;

ptr+=nread;

}

returnn-nleft;

}

5.1.2writen函数

ssize_twriten(intfd,constvoid*vptr,size_tn)

ssize_tnwritten;

constchar*ptr;

nleft=n;

if((nwritten=write(fd,ptr,nleft))<

=0){

if(nwritten<

0&

&

errno==EINTR)

{

nwritten=0;

}

nleft-=nwritten;

ptr+=nwritten;

returnn;

5.1.3readline函数

ssize_treadline(intfd,void*vptr,size_tmaxlen)

ssize_tn,rc;

charc,*ptr;

for(n=1;

n<

maxlen;

n++){

again:

if((rc=read(fd,&

c,1))==1){

*ptr++=c;

if(c=='

\n'

break;

}elseif(rc==0){

*ptr=0;

return(n-1);

}else{

gotoagain;

return-1;

*ptr=0;

5.2错误退出函数

stdarg.h>

syslog.h>

intdaemon_proc;

staticvoiderr_doit(int,int,constchar*,va_list);

voiderr_ret(constchar*fmt,...)

va_listap;

va_start(ap,fmt);

err_doit(1,LOG_INFO,fmt,ap);

va_end(ap);

return;

voiderr_sys(constchar*fmt,...)

err_doit(1,LOG_ERR,fmt,ap);

exit

(1);

voiderr_dump(constchar*fmt,...)

abort();

voiderr_msg(constchar*fmt,...)

err_doit(0,LOG_INFO,fmt,ap);

return;

voiderr_quit(constchar*fmt,...)

err_doit(0,LOG_ERR,fmt,app);

staticvoiderr_doit(interrnoflag,intlevel,constchar*fmt,va_listap)

interrno_save,n;

charbuf[MAXLINE+1];

errno_save=errno;

#ifdefHAVE_VSNPRINTF

vsnprintf(buf,MAXLINE,fmt,ap);

#else

vsnprintf(buf,fmt,ap);

#endif

n=strlen(buf);

if(errnoflag)

snprintf(buf+n,MAXLINE-n,"

:

%s"

sterror(errno_save));

strcat(buf,"

\n"

);

if(daemon_proc){

syslog(level,buf);

else{

fflush(stdout);

fputs(buf,stderr);

fflush(stderr);

6并发服务器

6.1Main函数

intmain(intargc,char**argv)

intlistenfd,connfd;

pid_tchildpid;

voidsig_chld(int),sig_int(int),web_child(int);

socklen_tclilen,addrlen;

structsockaddr*cliaddr;

if(argc==2)

listenfd=Tcp_listen(NULL,argv[1],&

addrlen);

elseif(argc==3)

listenfd=Tcp_listen(argv[1],argv[2],&

else

err_quit("

usage:

serv01[<

host>

]<

port#>

"

cliaddr=malloc(addrlen);

signal(SIGCHLD,sig_child);

signal(SIGINT,sig_int);

for(;

;

){

clilen=addrlen;

if((connfd=accept(listenfd,cliaddr,&

clilen))<

0){

if((errno==EINTR)

continue;

err_sys("

accepterror"

if((childpid=fork())==0){

close(listenfd);

web_child(connfd);

exit(0);

close(connfd);

在该代码中使用了到的函数:

消息响应函数sig_chld和sig_int,输入信息处理函数web_child,tcp监听函数Tcp_listen等四个函数。

6.2Sig_chld函数

源代码为每个客户连接fork一个子进程并处理来自垂死的子进程的SIGCHLD信号。

sig_chld代码如下:

voidsig_chld(intsigno)

pid_tpid;

intstat;

while((pid=waitpid(-1,&

stat,WNOHANG))>

;

在一个循环内调用waitpid,以获取所有已终止子进程的状态。

必须指定WNOHANG选项,它告知waitpid在有还没有终止的子进程在运行时不要阻塞。

不能在循环中调用wait,因为thereisnowaytopreventwaitfromblockingiftherearerunningchildrenthathavenotyetterminated.这里就用英语了,翻译的实在是太烂了。

6.3Sig_int函数

捕获由键入终端中终端键产生的sigint信号。

在客户运行完毕之后我们键入该键以显示服务器程序运行所需的CPU时间。

这是一个信号处理函数不返回而直接终止进程的例子。

voidsig_int(intsigno)

voidpr_cpu_time(void);

pr_cpu_time();

exit(0);

这里又用到了pr_cpu_time函数。

6.4Pr_cpu_time函数

#ifndefHAVE_GETRUSAGE_PROTO

intgetrusage(int,structrusage*);

#endif

voidpr_cpu_time(void)

doubleuser,sys;

structrusagemyusage,childusage;

if(getrusage(RUSAGE_SELF,&

myusage)<

err_sys("

getrusageerror"

if(getrusage(RUSAGE_CHILDREN,&

childusage)<

user=(double)myusage.ru_utime.tv_sec+myusage.ru_utime.tv_usec/1000000.0;

user+=(double)childusage.ru_utime.tv_sec+childusage.ru_utime.tv_usec/1000000.0;

sys+=(double)childusage.ru_stime.tv_sec+childusage.ru_stime.tv_usec/100000.0;

printf("

\nusertime=%g,systime=%g\n"

user,sys);

getrusage函数被调用了两次,分别返回调用进程(RUSAGE_SELF)和它的所有已终止子进程(RUSAGE_CHILDREN)的资源利用统计。

所显示的值包括总的用户时间(耗费在执行用户进程上的CPU时间)和总的系统时间(CPUtimespendwithinthekernel,executingonbehalfofthecallingprocess).

6.5Web_child函数

客户在建立与服务器的连接之后通过该连接写出一行文本,指出需要有服务器返送多少字节的数据给客户。

这一点与http有些类似:

客户发送一个小请求,服务器响应以所期望的信息。

在http应用系统中,服务器通常在发送回所请求的数据之后就关闭连接,不过较新的版本允许使用持续连接(persistentconnection),为在某个时限以内到达的额外客户请求继续保持tcp连接开发一段时间。

在web_child函数中,服务器允许来自客户的额外请求。

#defineMAXN16384

voidweb_child(intsockfd)

intntowrite;

charline[MAXLINE],result[

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2