tcpip实验报告.docx
- 文档编号:9737335
- 上传时间:2023-02-06
- 格式:DOCX
- 页数:40
- 大小:27.88KB
tcpip实验报告.docx
《tcpip实验报告.docx》由会员分享,可在线阅读,更多相关《tcpip实验报告.docx(40页珍藏版)》请在冰豆网上搜索。
tcpip实验报告
TCP/IP技术实验指导书
李沁编写
专业网络工程
班级104
学号109074
姓名
指导教师李沁
安徽工业大学计算机学院
二○一三年六月
实验一熟悉Linux编程环境3
实验二实现Echo服客户端程序(UDP)8
实验三循环无连接服务器Echo的实现11
实验四循环的、面向连接服务器的实现16
实验五并发的、面向连接服务器的实现18
实验六单进程并发服务21
实验七并发客户端25
实验八多线程服务29
实验九预分配进程服务器33
1.实验总体目标
配合TCPIP技术课程的教学,加强学生对TCP/IP编程技术的理解,培养学生的实际编程能力。
2.实验课时分配
序号
实验项目
学时
试验类型
实验一
熟悉Linux编程环境
2
综合性
实验二
实现Echo服务客户端程序(UDP)
2
综合性
实验三
循环无连接服务器的实现
2
综合性
实验四
循环的、面向连接服务器的实现
2
综合性
实验五
并发的、面向连接服务器的实现
2
综合性
实验六
单进程并发服务
2
综合性
实验七
并发的客户端
2
综合性
实验八
多线程服务
2
综合性
实验九
预分配进程服务器
2
综合性
3.实验环境
开发工具:
gcc以及编辑器(gedit,vi)
操作系统:
Linux2.6以上
4.实验总体要求
●按照各项实验内容做实验,包括操作、观察、记录、分析,通过操作和观察获得直观印象,从获得的数据中分析网络协议的工作原理;
●每项实验均提交实验报告,实验报告的内容可参照实验的具体要求,但总体上应包括以下内容:
实验准备情况,实验记录,实验结果分析,算法描述,程序段,实验过程中遇到的问题以及对思考问题的解答等,实验目的、实验原理、实验步骤不需要写入实验报告中。
实验一熟悉Linux编程环境
【实验目的】
1.掌握gcc的基本使用方法。
2.掌握fork函数的使用方法。
3.掌握exeve函数的使用方法。
【实验原理】
一、gcc的基本编译命令
设定编译出的object档档名或是可执行档档名:
参数:
-oout_put_filename
说明:
指定编译出的档名为out_put_filename。
范例:
本例将程式码'test.c'编译成可执行档,并设定档名为'test'。
gcctest.c–otest
二、fork函数
父进程调用fork函数创建子进程,返回值分别为0和子进程的PID,前者返回给子进程,后者返回给父进程。
父子进程根据返回的PID确定将要继续执行的指令。
例:
intpid;
sum=0;
pid=fork();
if(pid!
=0){/*originalprocess*/
printf("Theoriginalprocessprintsthis.\n");
}
else{
printf("Thenewprocessprintsthis.\n");
三、execve函数
intexecve(
constchar*pathname,
char*constargv[],char*constenvp[]);
函数说明execve()用来执行参数filename字符串所代表的文件路径,第二个参数系利用数组指针来传递给执行文件,最后一个参数则为传递给执行文件的新环境变量数组。
返回值 如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。
例:
#include
#include
intmain(intarg,char**args)
{
//char*name="/usr/bin/ls";
char*argv[]={"ls","-l","/cway-linux/source",NULL};
//传递给执行文件的参数数组,这里包含执行文件的参数
char*envp[]={0,NULL};//传递给执行文件新的环境变量数组
execve("/bin/ls",argv,envp);
}
【实验步骤】
一、
练习1:
编写一个并发程序,利用fork函数创建五个进程,让每一个进程打印出可用来分辨不同进程的信息。
练习2:
编写一个程序,利用execve函数改变进程执行的代码。
二、利用gcc编译程序
三、执行程序观察程序输出
试验一熟悉Linux编程环境
实验时间:
_____________成绩:
________________
练习1:
编写一个并发程序,利用fork函数创建五个进程,让每一个进程打印出可用来分辨不同进程的信息。
#include
#include
#include
intmain()
{
intpid,i;
i=0;
while(i<5)
{
i++;
if((pid=fork())==0)
{
printf("pid:
%d\n",getpid());
sleep(3);
break;
}
waitpid(pid,(int*)0,0);
printf("ppid:
%d\n",getpid());
}
return0;
}
运行结果:
练习2:
编写一个程序,利用execve函数改变进程执行的代码。
//execve.c
#include
#include
#include
intmain(intargc,char*argv[])
{
char*newargv[]={NULL,"you","me",NULL};
char*newenviron[]={NULL};
if(argc!
=2)
{
fprintf(stderr,"Usage:
%s
exit(EXIT_FAILURE);
}
newargv[0]=argv[1];
execve(argv[1],newargv,newenviron);
perror("execve");
exit(EXIT_FAILURE);
}
//myecho.c
#include
#include
#include
intmain(intargc,char*argv[])
{
inti;
for(i=0;i printf("argv[%d]: %s\n",i,argv[i]); return0; } 运行: ./execvemyecho 结果: cwjuneva@ubuntu: ~$geditexecve.c cwjuneva@ubuntu: ~$geditmyecho.c cwjuneva@ubuntu: ~$gcc-omyechomyecho.c cwjuneva@ubuntu: ~$./execvemyecho argv[0]: myecho argv[1]: you argv[2]: me 实验二实现Echo服客户端程序(UDP) 【实验目的】 1.掌握客户端程序的基本结构 2.掌握如何形成socket地址 3.掌握在UDP的套接字上读写数据 【实验环境配置】 Linux,开启echo后台服务 【实验原理】 一、获取系统当前时间API: #include intgettimeofday(structtimeval*tv,structtimezone*tz); 保存时间的结构体 struttimeval{ longtv_sec;/*秒数*/ longtv_usec;/*微秒数*/}; 例子: #include #include intmain(){ structtimevaltpstart,tpend; doubletimeuse; inti=0; gettimeofday(&tpstart,NULL); for(i=0;i<1000000000;i++); printf("%d,i); gettimeofday(&tpend,NULL); timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec; timeuse/=1000000; printf("processortimeis%lfs\n",timeuse); return0;} 二、参阅教材6、7两章的代码理解客户端echo程序的结构以及相关socket系统调用 【实验步骤】 1.实现教材第7章练习第11题,对echo客户端程序进行改进,实现简单超时重传。 (可以利用alarm函数或者select函数) 2.启动系统后台echo服务,测试编写的程序能否与后台echo交互(127.0.0.1) 3.关闭后台echo服务,测试编写的程序能否重传(在标准输出上显示相邻重传之间的时间间隔) 实验二实现Echo服务客户端程序(UDP) 实验时间: _____________ //client.c #include #include #include #include #include #include #include #include #include #include intreadable_timeo(intfd,intsec) { fd_setrset; structtimevaltv; FD_ZERO(&rset); FD_SET(fd,&rset); tv.tv_sec=sec; tv.tv_usec=0; return(select(fd+1,&rset,NULL,NULL,&tv));//使用select函数实现简单超时重传 } intmain(intargc,char**argv) { intsockfd,len,res,i; structsockaddr_inaddress; char*host; structhostent*hostinfo; structservent*servinfo; charbuf[128],buf2[128]; intnsec=20;//timeout: 20s structtimevaltpstart,tpend; doubletimeuse; if(argc==1) host="localhost"; else host=argv[1]; hostinfo=gethostbyname(host); if(! hostinfo) { fprintf(stderr,"nohost: %s\n",host); exit (1); } servinfo=getservbyname("echo","udp"); if(! servinfo) { fprintf(stderr,"noechoserver! \n"); exit (1); } sockfd=socket(AF_INET,SOCK_DGRAM,0); address.sin_family=AF_INET; address.sin_port=servinfo->s_port; address.sin_addr=*(structin_addr*)*hostinfo->h_addr_list; len=sizeof(address); while(fgets(buf,128,stdin)! =NULL) { for(i=0;i<2;i++)//juseonechancetoresend { if(i==1)//resend { printf("ReSend! ! ! \n"); gettimeofday(&tpend,NULL); timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec; timeuse/=1000000; printf("resendtimeis%lfs\n",timeuse); } gettimeofday(&tpstart,NULL); res=sendto(sockfd,buf,strlen(buf),0,(structsockaddr*)&address,len); if(readable_timeo(sockfd,nsec)==0) { fprintf(stderr,"sockettimeout\n"); continue; } res=recvfrom(sockfd,buf2,128,0,(structsockaddr*)&address,&len); buf2[res]=0; fputs(buf2,stdout); break;//sendsuccessfully,quit! } } close(sockfd); exit(0); } 实验三循环无连接服务器Echo的实现 【实验目的】 1.掌握服务器程序套接字构造方法 2.掌握实现迭代服务的程序结构 【实验原理】 一、服务器端构造UDP套接字 constchar*service;//nameofservice constchar*transport;//tcporudp intqlen;//thesizeofrequestqueue /* *Arguments: *service-serviceassociatedwiththedesiredport *transport-transportprotocoltouse("tcp"or"udp") *qlen-maximumserverrequestqueuelength */ { structservent*pse;/*pointertoserviceinformationentry*/ structprotoent*ppe;/*pointertoprotocolinformationentry*/ structsockaddr_insin;/*anInternetendpointaddress*/ ints,type;/*socketdescriptorandsockettype*/ memset(&sin,0,sizeof(sin)); sin.sin_family=AF_INET; sin.sin_addr.s_addr=INADDR_ANY;//localIPinterfacedeterminedbykernel /*Mapservicenametoportnumber*/ if(pse=getservbyname(service,transport)) sin.sin_port=htons(ntohs((unsignedshort)pse->s_port) +portbase);//portbaseisusedtopreventcollisionwithwell-knownports elseif((sin.sin_port=htons((unsignedshort)atoi(service)))==0) errexit("can'tget\"%s\"serviceentry\n",service); /*Mapprotocolnametoprotocolnumber*/ if((ppe=getprotobyname(transport))==0) errexit("can'tget\"%s\"protocolentry\n",transport); /*thestructureofsockethasbeenfilledcompletelysofar*/ /*Useprotocoltochooseasockettype*/ if(strcmp(transport,"udp")==0) type=SOCK_DGRAM; else type=SOCK_STREAM; /*Allocateasocket*/ s=socket(PF_INET,type,ppe->p_proto); if(s<0) errexit("can'tcreatesocket: %s\n",strerror(errno)); /*Bindthesocket*/ if(bind(s,(structsockaddr*)&sin,sizeof(sin))<0) errexit("can'tbindto%sport: %s\n",service, strerror(errno)); if(type==SOCK_STREAM&&listen(s,qlen)<0) errexit("can'tlistenon%sport: %s\n",service, strerror(errno)); returns; 二、获取socket信息的系统API #include intioctl(intfd,intrequest,.../*void*arg*/); fd是文件描述符,request是希望对fd执行的操作,当要获取socket信息时为SIOCGIFCONF.当调用ioctl函数前,我们需要首先创建一个ifcong结构并初始化(对ifc_len赋以一个足够的长度),并将其地址作为ioctl函数的第三个参数。 下面是ifcong结构的定义: structifconf{ intifc_len;/*sizeofbuffer,value-result*/ union{ caddr_tifcu_buf;/*inputfromuser->kernel*/ structifreq*ifcu_req;/*returnfromkernel->user*/ }ifc_ifcu; }; 下面是ifreq结构的定义: #defineIFNAMSIZ16 structifreq{ charifr_name[IFNAMSIZ];/*interfacename,e.g.,"le0"*/ union{ structsockaddrifru_addr; structsockaddrifru_dstaddr; structsockaddrifru_broadaddr; shortifru_flags; intifru_metric; caddr_tifru_data; }ifr_ifru; }; 【实验步骤】 实现服务端程序,需满足: 1.无连接、循环服务。 2.利用实验二的客户端程序向服务器程序请求服务,每次收到请求时在本地终端上输出客户端的IP地址和本次服务的时间。 3.客户端多次请求服务,观察服务器对客户端的反馈和本地终端输出,判断是否正确实现迭代服务。 试验三循环无连接服务器Echo的实现 实验时间: _____________ //server.c #include #include #include #include #include #include #include #include #include #include #defineMAXLINE128 intsockfd,flag=1; voidclose_action(intsig) { printf("closethesockfd\n"); close(sockfd); signal(SIGINT,SIG_DFL); flag=0; } intmain() { structsockaddr_insin,sin_cli; inttype,res,opt; charmesg[MAXLINE],buf[MAXLINE]; socklen_tlen; structsigactionact; structtm*ptm; inty,m,d,h,n,s; longts; //setthesignalaction act.sa_handler=close_action; sigemptyset(&act.sa_mask); act.sa_flags=0; memset(&sin,0,sizeof(sin)); sin.sin_family=AF_INET; sin.sin_addr.s_addr=INADDR_ANY; sin.sin_port=htons(45454); sockfd=socket(AF_INET,SOCK_DGRAM,0); if(sockfd<0) { fprintf(stderr,"can'tcreatesocket%s\n",strerror(errno)); exit (1);
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- tcpip 实验 报告