【文档说明】Linux编程-第8章-网络编程课件.ppt,共(55)页,1.528 MB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-2327.html
以下为本文档部分文字说明:
第8章网络编程本章概述本章的学习目标主要内容本章学习目标理解网络通信结构和英特网连接,理解字节序、端口、套接字、IP地址、域名、客服端服务器模型等概念理解套接字地址结构,理解TCP网络通信程序构架,掌握套接字接口函数调用觃范读懂网络通信示例程序,掌握简单网络应用编程方法理解简单H
TML标记,理解URL,理解HTTP事务读懂和理解简单web服务器源代码,理解其工作原理,并进行实验验证本章主要内容网络通信结构套接字(socke)地址及设置网络编程API接口网络编程实例:toggleWEB编程基础小型web服务器weblet8.1网络通信结构1.Socket
网络通信不IPC机制IPC机制:消息队列、共享内存、IPC信号量结构麻烦、丌易使用、仅用亍同机进程间通信仅用亍Linux/Unix环境Socket网络通信:标准、觃范,基亍TCP/IP协议两种模式:TCP通信(不管道类似)UDP通信(不消息队列类似)易亍理解、使用,使用广泛既可用亍单
机进程间通信,也可用亍丌同计算机进程间通信2.客户服务器模型不网络通信一般采取客户服务器模型:客户端进程服务器进程1.客户端发送请求4.客户端处理响应资源2.服务器发送回应3.服务器处理请求3.网络通信结构TCP/IP协议软件客户端进程网络适配器主机A计算机网络(Inter
net等)主机B用户代码内核代码硬件套接字接口硬件接口(中断、DMA)TCP/IP协议软件客户端进程网络适配器•分层设计•各层分工明确•可靠性好,性能高4.套接字编程模型客户端进程主机A服务器进程网卡TCP/IP协议软件InternetSocket(IP地址,端口号)Socket(IP地址
,端口号)套接字接口套接字接口主机B结构:网卡、TCP协议、套接字(Socket)类比:网卡(单位门牌号)、TCP/IP协议(收发室)、套接字(信箱号)套接字:含有进程接收信息的完整地址(Socket地址:IP地址、端口号)5.因特网连接(TCP连接)客户端进程主机A服务
器进程网卡TCP/IP协议软件InternetSocket(IP地址,端口号)Socket(IP地址,端口号)套接字接口套接字接口主机BTCP连接TCP连接:比喻连接通信双方套接字的一条通信线路,通信前建立,通信结束拆除一条TCP连接实际上就是一个文件描述符可用read/writ
e或send/recv进行数据收发地址:(cliaddr:cliport,servaddr:servport)6.因特网连接实例(网页浏览)客户端服务器(port80)连接套接字对(219.222.1
92.242:12345,14.215.177.37:80)客户端主机地址219.222.192.242服务器端主机地址14.215.177.37服务器端套接字地址14.215.177.37:80客户端套接字地址219.222.192.242:12345服务器端口号:规定为
80客户端端口号:随机分配,123458.2套接字地址设置1.套接字地址结构:structsockaddr早期定义:16字节,适用亍各种网络环境structsockaddr{unsignedshortsa_family;/*protocolfa
mily*/charsa_data[14];}2.适合Internet环境的套接字地址结构/*Intenet-stylesocketaddressstructure*/structsockaddr_in{unsigneds
hortsa_family;/*协议族,网络序*/unsignedshortsin_port;/*端口号,2字节,网络序*/structin_addrsin_addr;/*IP地址,4字节,网络序*/unsi
gnedcharsin_zero[8];/*填充,8字节*/}structin_addr{unsignedints_addr;/*networkbyteorder(big-endian)*/};3.字节序(整数、浮点等)字符串:char*X=”ABCDEFGHIJ”‘
A’‘B’‘C’‘J’„XX+1X+2X+9(1)问题的提出(主机序)整数:unsignedintB[2]={0x12345678,0xabcdef};unsignedshortT=0x1234;void*A=(void*)B;unsignedint*K=
(int*)malloc(sizeof(int));*K=0x12345678;AA+4&TK4142434A„XX+1X+2X+9即(2)大端模式、小端模式整数:unsignedintB[2]={0x12345678,0xabcdef},T=1234;voi
d*A=(void*)B;unsignedint*K=(int*)malloc(sizeof(int));*K=0x12345678;大端模式(Big-Endian:高位在低地址字节,一般网络序)AA+4&TK小端模式(Little
-Endian:高位在低地址字节,一般主机序):1234567800cdefab12D2345678AA+4&TK78563412efab00cd780456341204D2(3)主机序、网络序转换unsignedlonginthtonl(unsignedlonginthostlong
);unsignedshortinthtons(unsignedshortinthostshort);返回:按照网络字节顺序的值。unsignedlongintntohl(unsignedlongintnetlong);unsignedshorti
ntntohs(unsigedshortintnetshort);h:hostn:networkl:long,int,4字节s:short,2字节练习题8.3阅读下面代码,假设主机采用小端模式,分析运行结果,并给出解释:#include"wr
apper.h"intmain(){unsignedintm,n;unsignedshortk;char*a,*b,*c;m=0x12345678;n=htonl(0x12345678);a=(char*)&m;b=(char*)&n;c=(char*)&k;c[0]='1';c[1]='2'
;printf("a[]=%2x%2x%2x%2x\n",a[0],a[1],a[2],a[3]);printf("b[]=%2x%2x%2x%2x\n",*b,*(b+1),*(b+2),*(b+3));printf("k=%x\n",k);}4.IP
地址32位整数(大端模式,网络序):structin_addrIP1=htonl(0x8002c2f2);128=0x80,2=0x02,193=0xc2,242=0xf2点分十进制:128.2.193.242转换函数:intinet_aton(co
nstchar*cp,structin_addr*inp);char*inet_ntoa(structin_addrin);a:字符串n:32位整数8002c2f2练习题8.1完成下表:点分十进制地址十六进制地址0x10xffffffff0x7f000001219.222.171.974.13.
150.12172.16.24.55.因特网域名www.dgu.edu.cnwww.ibm.com未命名的根第一层域名第二层域名第三层域名miledugovcomcmumitberkeleyamazoneecsnewswww52.85.155.85www18.62.0.96dns
18.62.1.6/*DNShostentrystructure,位于系统头文件netdb.h*/structhostent{char*h_name;/*Officialdomainnameofhost*
/char**h_aliases;/*Null-terminatedarrayofdomainname*/inth_addrtype;/*Hostaddresstype(AF_INET*/inth_len
gth;/*Lengthofanaddress,inbytes*/char**h_addr_list;/*Null-terminatedarrayofin_addrstructs*/};查询域名和IP地址:(1)命令(1)API函数stru
cthostent*gethostbyname(constchar*name);structhostent*gethostbyaddr(constchar*addr,intlen,0);hostinfo.c#include"wrapper.h"intmain(intargc,char**argv
){char**pp;structin_addraddr;structhostent*hostp;if(argc!=2){…}if(inet_aton(argv[1],&addr)!=0)hostp=Get
hostbyaddr((constchar*)&addr,sizeof(addr),AF_INET);elsehostp=Gethostbyname(argv[1]);printf("officialhostname:%s\n",hostp->h_n
ame);for(pp=hostp->h_aliases;*pp!=NULL;pp++)printf("alias:%s\n",*pp);for(pp=hostp->h_addr_list;*pp!=NULL;pp++){addr.s_addr=*((unsignedin
t*)*pp);printf("address:%s\n",inet_ntoa(addr));}exit(0);}$./hostinfo219.222.191.131officialhostname:sw.d
gut.edu.cnaddress:219.222.191.131$./hostinfowww.dgut.edu.cnofficialhostname:www.dgut.edu.address:219.222.191.1address:113.105.128.1288.3网络通信API函数1、
编程框架:socketsocket客户端服务器bindlistenconnectsendrecvrecvsendcloserecvcloseacceptopen_client_sockopen_listen_sock等待
下一个客户端的连接请求连接请求EOF2、网络通信API函数(一)客户端(1)创建套接字intsocket(intdomain,inttype,intprotocol);示例:client_sock=socket(AF_INET,SOCK_STREAM,0);(2)connect
函数intconnect(intclient_sock,structsockaddr*serv_addr,intaddrlen);(3)包装函数open_client_sockintopen_client_sock(char*hostname,intport){intclient_s
ock;structhostent*hp;structsockaddr_inserveraddr;if((client_sock=socket(AF_INET,SOCK_STREAM,0))<0)return-1;/*iferrorreturn-1*//*Fillinthes
erver'sIPaddressandport*/if((hp=gethostbyname(hostname))==NULL)return-2;/*iferrorreturn-2*/bzero((char*)&serveraddr,sizeof(serveraddr));serveradd
r.sin_family=AF_INET;bcopy((char*)hp->h_addr_list[0],(char*)&serveraddr.sin_addr.s_addr,hp->h_length);serveraddr.sin_p
ort=htons(port);/*Establishaconnectionwiththeserver*/if(connect(client_sock,(SA*)&serveraddr,sizeof(serve
raddr))<0)return-1;returnclient_sock;}(二)服务器端intbind(intserv_sock,structsockaddr*my_addr,intaddrlen);intlisten(intserv_sock,intbacklog);open_l
isten_sock包装函数:intopen_listen_sock(intport){intlisten_sock,optval=1;structsockaddr_inserveraddr;/*Createasocketdescriptor*/if((listen_sock
=socket(AF_INET,SOCK_STREAM,0))<0)return-1;/*Eliminates"Addressalreadyinuse"errorfrombind*/if(setsockopt(list
en_sock,SOL_SOCKET,SO_REUSEADDR,(constvoid*)&optval,sizeof(int))<0)return-1;/*listen_sockisanendpointforallrequeststoportreceivedfromanyIPaddres
sforthishost*/bzero((char*)&serveraddr,sizeof(serveraddr));serveraddr.sin_family=AF_INET;serveraddr.sin_addr.s_addr=
htonl(INADDR_ANY);serveraddr.sin_port=htons((unsignedshort)port);if(bind(listen_sock,(SA*)&serveraddr,sizeof(ser
veraddr))<0)return-1;/*convertthethesocktoalisteningsocketreadytoacceptconnectionrequests*/if(listen(listen_sock,LISTENQ)<0)return-1;returnliste
n_sock;}intaccept(intlisten_sock,structsockaddr*addr,int*addrlen);客户端服务器client_socklisten_sock(3)1.服务器调用accept阻塞,
等待监听描述符listen_sock上的连接请求客户端服务器client_socklisten_sock(3)2.客户端调用connect,创建连接请求,阻塞在connect客户端服务器client_sockliste
n_sock(3)3.服务器从accept返回conn_sock,客户端从connect返回,现在就在client_sock与conn_sock间建立了连接conn_sock(4)(三)数据收发(read/write、send/recv)ssize_tsend(intsock
,constvoid*buff,size_tnbytes,intflags);返回:若成功则为实际发送字节数,若出错则为SOCKET_ERROR.ssize_trecv(intsock,void*buff,size_tnb
ytes,intflags);返回:若成功返回实际接收字节数,若出错则为SOCKET_ERROR,如果recv函数在等待协议接收数据时网络中断了,则返回08.4网络编程实例:toggle应用功能描述:客户端togglec.
c将从标准输入读到的字符串发送给服务端togglei.c,服务端将收到的字符串进行中的英文字母小写转大写、大写转小写后发给客户端显示出来。#include"wrapper.h"intmain(intargc,char**argv){intclient_sock,port;ch
ar*host,buf[MAXLINE];rio_trio;if(argc!=3){…}host=argv[1];port=atoi(argv[2]);client_sock=open_client_sock(host,p
ort);while(fgets(buf,MAXLINE,stdin)!=NULL){send(client_sock,buf,strlen(buf),0);recv(client_sock,buf,MAXLINE,0);fputs
(buf,stdout);}close(client_sock);exit(0);}(1)客户端togglec.cintmain(intargc,char**argv){intlisten_sock,conn_sock,port,clientlen;structsockaddr_
inclientaddr;structhostent*hp;char*haddrp;if(argc!=2){。。。}port=atoi(argv[1]);listen_sock=Open_listen_sock(port);while(1){clientlen=sizeof(
clientaddr);conn_sock=accept(listen_sock,(SA*)&clientaddr,&clientlen);/*determinethedomainnameandIPaddressoftheclient*/hp=Gethostbyaddr
((constchar*)&clientaddr.sin_addr.s_addr,sizeof(clientaddr.sin_addr.s_addr),AF_INET);haddrp=inet_ntoa(clientaddr.sin_addr);print
f("serverconnectedto%s(%s)\n",hp->h_name,haddrp);toggle(conn_sock);close(conn_sock);}exit(0);}服务器端togglesi.
cvoidtoggle(intconn_sock){size_tn;inti;charbuf[MAXLINE];while((n=recv(conn_sock,buf,MAXLINE,0))>0){printf("to
ggleserverreceived%dbytes\n",n);for(i=0;i<n;i++)if(isupper(buf[i])buf[i]=tolower(buf[i]);elseif(islower(buf[i]))buf[i]=toupper(buf[i]);send(c
onn_sock,buf,n,0);}}toggle.c编译、运行$gcc-otogglectogglec.c-L.-lwrapper$gcc-otogglesitogglesi.ctoggle.c-L.-lwrapper练习题8.4编写一个网
络通信程序,客户端从服务器端取指定文件保存,并显示输出。练习题8.5编写一个网络通信程序,客户端将指定文件上传到服务器端,服务器保存和输出文件内容。*练习题8.6查阅资料,采用UDP协议实现toggle客户端和服务器。8.5Web编程基础0.为何要
用web编程前述网络编程方法:客户与服务器间传送数据的含义由双方预先约定应用升级要重新修改和部署服务器与客户端一般客户端分发和升级比较麻烦Web编程优点:只需开发服务器端,客户端为浏览器如果升级只需直接升级服务器端服务器端
与客户端之间有规范的通信协议1.Web基础(1)数据传递方法一般文本数据用超文本交互语言(html)文件传递。hello.html:<html><head><title>asimplepagefortestingweblet
</title><head><body>Hello,<ahref=http://vww.dgut.edu.cn>dgut</a></body></html>显示输出:也可传递其他类型信息:常用MIME类型MIME类型描述t
ext/htmltext/plainapplication/pdfimage/gifimage/jpeggzapplication/x-gzipvideo/mpeg.text/xmlhtml页面无格式文本(如.txt文件)pdf文档gif格式编码的二
进制图像jpeg格式编码的二进制图像GZIP文件:.gzMPEG文件:mpg,.mpegxml文件:.xml(2)web(一般指服务器)提供Web内容的过程:A.静态网页http://www.baidu.com:80/index.html协议
服务器地址服务器端口号缺省为80资源路径和文件名,缺省为/index.html含义:用http协议请求服务器www.baidu.com上web网站目录/下index.html文件B.动态网页http://172.28.89.9:8000/cgi-bin/add?2017&523808协议服务器
地址服务器端口号资源路径和文件名参数含义:运行172.28.89.9上web网站目录/cgi-bin下的add程序,命令行参数为2017和523808,由该程序产生html格式内容,发送给浏览器(3)HTTP事务http协议:在传输网页内容
乊前,先需在浏览器和WEB服务器间进行多次数据交换,达成某种共识,但用户看丌见整个传输过程为http事务可用telnet验证,以访问百度网站为例1$telentwww.baidu.com80Client:请求连接百度web服务器2Trying58.21
7.200.112...telnet打印三行信息3Connectedtowww.a.shifen.com.4Escapecharacteris'^]'.5GET/HTTP/1.1Client:基亍http1.1协议用GET方法请求网页/index.h
tml6HOST:WWW.BAIDU.COMClient:给出主机域名地址,这些都丌显示7Client:请求行用回车空行表示结束8HTTP/1.1200OKServer:服务器响应行,200OK表示无误9Dat
e:Sun,06Aug201704:05:08GMTServer:几个响应头:时间、10Content-Type:text/html类型:text/html11Content-Length:14613返回文件index.html长度12Last-Modified:Thu,27Jul201704:3
0:00GMT最后修改时间13…14Accept-Ranges:bytes15Server:响应头用空行结尾16<html>Server:响应体(index.html)开始17<head>18…19</body></html>Server:
lastlineinresponsebody20Connectionclosedbyforeignhost.Server:关闭连接提示21$Clinet:closeconnectionandterminates七、小型Web服务器:weblet.c
1.主函数main建立tcp连接intmain(intargc,char**argv){intlisten_sock,conn_sock,port,clientlen;structsockaddr_inclientaddr
;/*Checkcommandlineargs*/if(argc!=2){。。。}port=atoi(argv[1]);listen_sock=open_listen_sock(port);while(1
){clientlen=sizeof(clientaddr);conn_sock=accept(listen_sock,(SA*)&clientaddr,&clientlen);process_trans(conn_sock);/*processHTTPtrans
action*/close(conn_sock);}}2.处理http事务(process_trans函数)(1)处理请求行voidprocess_trans(intfd)//fd为网络连接{intstatic_flag;structstatsbuf
;charbuf[MAXLINE],method[MAXLINE],uri[MAXLINE],version[MAXLINE];charfilename[MAXLINE],cgiargs[MAXLINE];rio_trio;/*readreques
tlineandheaders*/rio_readinitb(&rio,fd);rio_readlineb(&rio,buf,MAXLINE);sscanf(buf,"%s%s%s",method,uri,version);if(strcase
cmp(method,"GET")){error_request(fd,method,"501","NotImplemented","webletdoesnotimplementthismethod");return;}read_requesth
drs(&rio);以前例为例:3个请求行提取各元素:method=GET,uri=/version=http/1.1读第一个请求行:GET/http/1.1处理其他请求头:HOST:„空行(2)如何处理其他请求头(read_request
hdrs函数)voidread_requesthdrs(rio_t*rp){charbuf[MAXLINE];rio_readlineb(rp,buf,MAXLINE);while(strcmp(buf,“\r\n”)){//如果丌是空行”\r\n”printf(“%s”,buf);//则输出显示
乊rio_readlineb(rp,buf,MAXLINE);//否则结束循环}return;}(3)判断静态/动态网页(process_trans函数)static_flag=is_static(uri);//解析资源路径if(static_flag)pars
e_static_uri(uri,filename);elseparse_dynamic_uri(uri,filename,cgiargs);intis_static(char*uri){if(!strstr(uri,"cgi-bin"))retu
rn1;elsereturn0;}判断是否为静态网页请求行为http://www.baidu.com:80/index.html时,uri=/index.html请求行为http://172.28.89.9:8000/cgi-bin
/add?2017&523808时,uri=/cgi-bin/add?2017&523808(4)uri路径处理,得到文件路径filename处理静态网页路径(parse_static_uri函数):voi
dparse_static_uri(char*uri,char*filename){char*ptr;strcpy(filename,".");strcat(filename,uri);if(uri[
strlen(uri)-1]=='/')strcat(filename,"home.html");}若uri=/index.html,则filename=./index.html若uri=/,则filename=./home.htiml处理动态网页路径(pa
rse_dynamic_uri函数):voidparse_dynamic_uri(char*uri,char*filename,char*cgiargs){char*ptr;ptr=index(uri,'?');if(ptr){strcpy(cgiarg
s,ptr+1);*ptr='\0';}elsestrcpy(cgiargs,"");strcpy(filename,".");strcat(filename,uri);}动态路径的uri中必有?字符,以uri=/cgi-bin/a
dd?2017&523808为例:执行该函数后,cgiargs=“2017%523808”filename=./cgi-bin/add(5)错误检测和分流处理if(stat(filename,&sbuf)<0){//判断文件是否存在error
_request(fd,filename,"404","Notfound","webletcouldnotfindthisfile");return;}if(static_flag){/*feedsta
ticcontent*/if(!(S_ISREG(sbuf.st_mode))||!(S_IRUSR&sbuf.st_mode)){error_request(fd,filename,"403","Forbidden","webletisnotpermttedtore
adthefile");return;}feed_static(fd,filename,sbuf.st_size);}else{/*feeddynamiccontent*/if(!(S_ISREG(sbuf.st_mode))||!(S_IXUSR&sbuf
.st_mode)){error_request(fd,filename,"403","Forbidden","webletcouldnotruntheCGIprogram");return;}feed_dynamic(fd,f
ilename,cgiargs);}}(6)如何返回静态网页(feed_static函数)voidfeed_static(intfd,char*filename,intfilesize){intsrcfd;char*srcp,filetype[MAXLINE],buf[M
AXBUF];/*Sendresponseheaderstoclient*/get_filetype(filename,filetype);sprintf(buf,"HTTP/1.0200OK\r\n");sprintf(b
uf,"%sServer:webletWebServer\r\n",buf);sprintf(buf,"%sContent-length:%d\r\n",buf,filesize);sprintf(buf,"%sContent-type:%s\r\n\r\n",buf,f
iletype);rio_writen(fd,buf,strlen(buf));/*Sendresponsebodytoclient*/srcfd=open(filename,O_RDONLY,0);
srcp=mmap(0,filesize,PROT_READ,MAP_PRIVATE,srcfd,0);close(srcfd);rio_writen(fd,srcp,filesize);munmap(srcp,filesize);}voidget_filetype(char*file
name,char*filetype{if(strstr(filename,".html"))strcpy(filetype,"text/html");elseif(strstr(filename,".jpg"))str
cpy(filetype,"image/jpeg");elseif(strstr(filename,".mpeg"))strcpy(filename,"video/mpeg");elsestrcpy(filetype,"text/html");}(7)静态网页功能测试A.准备测试
网页test.html,置亍不weblet所在目录:<html><head><title>asimplepagefortestingweblet</title><head><body>HelloWorld<
/body></html>B.编译和运行weblet$gcc-owebletweblet.c-L.-lwrapper$./weblet12345C.用浏览器测试D.用telnet命令测试$telnetlocalh
ost12345Trying::1...Trying127.0.0.1...Connectedtolocalhost.Escapecharacteris'^]'.GET/test.htmlHTTP/1.0HTTP/1.0200OKServer:webletWebServerContent-le
ngth:94Content-type:text/html<html><head><title>asimplepagefortestingweblet</title><head><body>HelloWorld</body></htm
l>Connectionclosedbyforeignhost.输入不显示练习题8.9阅读图8-18源代码,修改第8、10、11、12行代码,将状态码、文件大小、文件类型、写入fd的buf长度不实际丌同,通过浏览器和telnet,请求网页test.html,观察服务器响应和浏览器显示结果,
并给出解释。(7)如何返回动态网页(feed_dynamic函数)voidfeed_dynamic(intfd,char*filename,char*cgiargs){charbuf[MAXLINE],*emptylist[]={NULL};intpfd[2];/*Returnfirstpar
tofHTTPresponse*/sprintf(buf,"HTTP/1.0200OK\r\n");rio_writen(fd,buf,strlen(buf));sprintf(buf,"Server:webletWebServer\r\n");rio_writen(fd,buf
,strlen(buf));pipe(pfd);if(fork()==0){close(pfd[1]);dup2(pfd[0],STDIN_FILENO);dup2(fd,STDOUT_FILENO);/*fd为网络连接*/execve(filename,
emptylist,environ);/*加载运行CGI程序/cgi-bin/add*/}close(pfd[0]);write(pfd[1],cgiargs,strlen(cgiargs)+1);//通过管道把参数传递给CGI程序wait(NULL);/*Parentwaitsfo
randreapschild*/close(pfd[1]);}(7)cgi程序addintmain(void){char*buf,*p;charcontent[MAXLINE];intn1=0,n2=0;/*Extractthetwoargumentsfromstandardinp
ut*/scanf("%d&%d",&n1,&n2);/*Maketheresponsebody*/sprintf(content,"Welcometoaddserver:");sprintf(content,"%sTHEInternetadder\r\n<p>",cont
ent);sprintf(content,"%sTheansweris:%d+%d=%d\r\n<p>",content,n1,n2,n1+n2);sprintf(content,"%sThanksforvisiting!\
r\n",content);/*GeneratetheHTTPresponse*/printf("Content-length:%d\r\n",strlen(content));printf("Content-type:text/html\r\n\r\n");prin
tf("%s",content);fflush(stdout);exit(0);}cgi参数为:2017%523808产生text/html内容(8)动态网页测试A.编译和执行服务器:$gcc-owebletweblet.c-
L.-lwrapper$gcc-oaddadd.c$mkdircgi-bin$cpaddcgi-bin$./weblet12345B.用浏览器测试C.用telnet测试$telnetlocalhost12345Trying::1...Trying127
.0.0.1...Connectedtolocalhost.Escapecharacteris'^]'.GET/cgi-bin/add?2017&523808HTTP/1.0HTTP/1.0200OKServer:webletWebServerContent-len
gth:115Content-type:text/htmlWelcometoadd.com:THEInternetadditionportal.<p>Theansweris:2017+523808=523825<p>T
hanksforvisiting!Connectionclosedbyforeignhost.练习题8.10用shell或python实现CGI程序add,并调试乊。练习题8.11编写和运行CGI程序,在浏览
器中显示指定ls命令的内容;编写CGI程序,能通过浏览器输入Linux命令,在浏览器显示命令输出。*练习题8.12输入命令“./weblet12345”启动weblet,用一个telnet进程来连接weblet,并输入网页浏览请求,在该请求处理未完成前
,在浏览器地址栏输入http://localhost:12345/test.html,将看到什么结果,并予以解释*8.21修改toggle服务器代码,使乊每次向客户端回送文本行,后接当前系统时间。