
| 姓名 | 学号 | 实验组 | |||
| 实验时间 | 2 | 指导教师 | 成绩 | ||
| 实验项目名称 | 实验一 面向连接的套接字程序设计 | ||||
| 实验目的 | 1、掌握控制台程序设计的基本方法; 2、掌握在该网络环境下如何利用套接字及TCP协议实现面向连接的网络通信; 3、了解利用面向连接的套接字通信的实现原理。 | ||||
| 实验内容 | 利用套接字提供的相关函数进行控制台程序的编制,要求服务器对来访的客户计数,并向客户报告这个计数值。客户建立与服务器的一个连接并等待它的输出。每当连接请求到达时,服务器生成一个可打印的字符串信息,将它在连接上发回,然后关闭连接。客户显示收到的信息,然后退出。 例如,对于服务器接收的第10次客户连接请求,该客户将收到并打印如下信息: This server has been contacted 10 times. | ||||
| 实验环境 | Pc机 VC++ 6.0环境(具体环境自己调整) | ||||
| 实验步骤 | 1.启动Visual C++6.0开发环境 从“开始”菜单中选择“程序| Microsoft Visual Studio 6.0 | Microsoft Visual C++ 6.0”,显示Visual C++6.0开发环境窗口。 2.创建一个项目 (1)单击File菜单中的New选项,显示New(新建)对话框。 (2)单击Project(项目)标签,在Project选项卡中,选择Win32 Console Application(Win32控制台应用程序向导)。在Location(位置)文本框中指定一个路径,在Project Name(项目名称)文本框中为项目输入一个名字(例如:lab1_Client),单击OK按钮。 (3)依据提示单击下一步按钮,直到最后一步点击完成按钮,完成项目的建立。 (4)项目建立好后,注意包含的各种头文件和相应的库文件。 3..编写源程序文件 参考程序见书p.42~45 (注意理解实现原理)
4.建立并运行可执行程序 (1)选择菜单命令Build | Build lab1_Client.exe,建立可执行程序。 如果程序无语法错误,此时便成功地生成了可执行程序(例如:lab1_Client.exe)。 如果程序有语法错误,则屏幕下方的状态窗口中会显示错误信息,根据这些错误信息对源程序进行修改后,重新选择菜单命令Build | Build lab1_Client.exe,建立可执行程序。 (2)在控制台界面输入命令行执行程序,观察屏幕的显示内容。 5.观察并记录程序运行结果。 | ||||
| 实验程序 | 客户端代码: #include #include #include #include #include #include #pragma comment(lib,"wsock32.lib") #define PROTOPORT 5188 extern int errno; char*localhost="localhost"; void main(int argc,char*argv[]) { WSADATA wsa; struct hostent *ptrh; struct sockaddr_in servaddr; int sockfd;//客户端的套接字描述符 unsigned short port; char *host; int n;//读取字符数 char buf[1000];//缓冲区,接收服务器发来的数据 // added for windows if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0){ fprintf(stderr, "winsock2 initiation failed/n"); exit(1); } memset((char*)& servaddr,0,sizeof(servaddr)); /*清空sockaddr结构*/ servaddr.sin_family = AF_INET; /*设置为internet协议簇*/ /*检查命令行参数,如果有,就抽取端口号;否则使用内定的默认值*/ if(argc>2){ port=atoi(argv[2]); /*如果指定了协议端口,就转换成整数*/ }else{ port=PROTOPORT; /*否则,使用默认端口号*/ } if(port>0) /*如果端口号是合法的数值,就将它装入网络地址结构*/ servaddr.sin_port=htons((u_short)port); else{ /*否则,打印错误信息并退出*/ fprintf(stderr,"bad port number %s\\n",argv[2]); exit(1); } /*检查主机参数并检查主机名*/ if(argc>1){ host=argv[1]; /*如果指定了主机名参数,就使用它*/ }else{ host=localhost; /*否则,使用默认值*/ } /*将主机名转换成相映的IP地址并复制到servaddr结构中*/ ptrh=gethostbyname(host); /*从服务器主机名得到相应的IP地址*/ if( (char *)ptrh==NULL ){ /*检查主机名的有效性,无效则退出*/ fprintf(stderr,"invalid host:%s\\n",host); exit(1); } memcpy(&servaddr.sin_addr,ptrh->h_addr,ptrh->h_length); /*创建一个套接字*/ sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd<0){ fprintf(stderr,"socket creation failed\\n"); exit(1); } /*请求连接到服务器*/ if (connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0){ fprintf(stderr,"connect failed\\n"); /*连接请求被拒绝,报错并退出*/ exit(1); } /*从套接字反复读数据,并输出到用户屏幕上*/ n=recv(sockfd,buf,sizeof(buf),0); while(n>0){ write(1,buf,n); n=recv(sockfd,buf,sizeof(buf),0); } /*关闭套接字*/ closesocket(sockfd); /*终止用户程序*/ exit(0); } 服务器代码: #include #include #include #include #include #include #pragma comment(lib,"wsock32.lib") #pragma comment(lib,"wsock32.lib") #define PROTOPORT 5188 /*监听套接字的默认协议端口号*/ #define QLEN 6 /*监听套接字的请求队列大小*/ int visits=0; /*对于客户机连接的计数*/ void main(int argc, char** argv) { WSADATA wsa; struct hostent *ptrh; // 指向主机列表中的一个条目的指针 struct sockaddr_in servaddr; //存放服务器网络地址的结构 struct sockaddr_in clientaddr; //存放客户端网络地址的结构 int listenfd; // 监听套接字描述符 int clientfd; //响应套接字描述符 unsigned short port; int alen; char buf[1000]; if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0){ //对Winsock进行初始化! fprintf(stderr, "winsock2 initiation failed/n"); exit(1); } memset((char*)& servaddr,0,sizeof(servaddr)); /*清空sockaddr结构*/ servaddr.sin_family=AF_INET; servaddr.sin_addr.s_addr = INADDR_ANY; //设置本地IP地址 /*检查命令行参数,如果有,就抽取端口号;否则使用内定的默认值*/ if(argc > 1){ port = atoi(argv[1]); } else{ port = PROTOPORT; } if(port > 0){ //测试端口号是否合法 servaddr.sin_port = htons(port); } else{ fprintf(stderr, "bad port number %s/n", argv[1]); //答应错误信息并退出 exit(1); } listenfd = socket(AF_INET, SOCK_STREAM, 0);//创建一个用于监听的流式接字 if(listenfd < 0){ fprintf(stderr, "socket creation failed/n"); exit(1); } if(bind(listenfd, (sockaddr *)&servaddr, sizeof(servaddr)) < 0){ fprintf(stderr, "bind failed/n");//将本地地址绑定到监听套接字 exit(1); } if(listen(listenfd, QLEN) < 0){//开始监听套接字请求队列长度 fprintf(stderr, "listen failed/n"); exit(1); } while(1){//服务器主循环——处理来自客户机断的连接请求 alen = sizeof(clientaddr);//接受请求并生成套接字 if((clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, &alen)) < 0){ fprintf(stderr, "accept failed/n"); exit(1); } visits++; sprintf(buf, "this server has been contacted %d time/n", visits); send(clientfd, buf, strlen(buf), 0); closesocket(clientfd);//关闭响应 } } | ||||
| 实验结果 及 分析 | 启动服务器端后: 实验执行成功 | ||||
| 实验总结 | |||||
| 指导教师意见 | 签名: 年 月 日 | ||||
