计算机网络实践设计报告
学院: 计算机 班级: 成教2012业余 教师: 李领治 学号: 姓名: 成绩: 实验目的:
掌握Winsock2.0套接字编程技术的基本方法。
实验要求:
运用TCP/IP Winsock2.0套接字编程技术,使用VC编写一个面向连接通信的服务端程序与客户端程序,服务器先与端口3000绑定,然后等待客户连接,连接成功后就可与客户端互相收、发信息。交互中,通信任一方只要发送 bye, 通信过程便自动结束。 实验源程序:
服务器程序:
#pragma comment (lib, "Ws2_32.lib") //Winsock 2 函数库
//-------------------------------------------------------
#include <conio.h>
#include <stdio.h>
#include <winsock2.h> //Winsock 2 函数头文件 //-------------------------------------------------------
bool InitSocket();
int main(int, char**)
{
struct sockaddr addr;
int len;
bool over;
char msg[255];
SOCKET sock, sersock;
if( !InitSocket() ) return 0;
//加载初始化 Winsock 2 动态链接库 Ws2_32.dll
sock = socket( AF_INET,SOCK_STREAM,0 );
//创建监听的流套接口
if( sock==INVALID_SOCKET ){ //不能创建,返回
printf("不能创建Socket!\n");
getch();
WSACleanup( ); //卸载Winsock 2动态链接库Ws2_32.dll
return 0; }
//设置本服务器IP地址和端口号
((sockaddr_in*)&addr)->sin_family = AF_INET;
//AF_INET:使用Internet 协议
((sockaddr_in*)&addr)->sin_port = htons(3000);
//服务器端口号3000
((sockaddr_in*)&addr)->sin_addr.s_addr = inet_addr("127.1.1.1"); //主机地址
//把套接口与地址绑定
bind(sock,&addr,sizeof(addr));
//服务进程准备接收套接口上的连接请求
listen(sock,1); //监听方式,准备接收连接请求:1--允许等待队列中的连接请求1个
//接受网络连接,生成新的套接口sersock标识这一连接
printf("等待客户连接!\n");
len = sizeof(addr);
sersock = accept( sock,&addr,&len );
//从等待队列中检取连接请求,如队列空则进程阻塞等待;
//如不空,则接受客户连接,使用返回连接套接口sersock与该客户连接。 //原套接口sock可继续监听其它客户请求。
if(sersock==INVALID_SOCKET) { //若套接口sersock 出错
DWORD err = WSAGetLastError();
char txt[100];
sprintf(txt,"error when accept!---errno:%d",err);
printf(txt);
getch();
closesocket(sock); //关闭监听套接口sock
WSACleanup( ); //卸载Winsock 2动态链接库Ws2_32.dll
return 0;
}
printf("有客户连接!\n输入bye通信结束\n");
over = false; //状态设置为未结束
//与客户交互会话,直至任一方打入bye后退出循环
do{
printf("\n等待对方用户输入信息......");
len = recv ( sersock,msg,200,0 ); //接收对方信息
printf("\n对方输入:%s",msg); //显示对方信息
if( strcmp(msg,"bye")==0 ) //若对方信息为bye就结束通信
break;
printf("\n本方回答:");
gets(msg); //键入本方信息
if( strcmp(msg,"bye")==0 ) over = true;
//若本方发出bye就结束通信 send ( sersock,msg,strlen(msg)+1,0 );
//将本方键入信息发给对方 } while( !over );
closesocket(sersock); //关闭连接套接口
closesocket(sock); //关闭监听套接口
printf("\n\n会话结束,按任一键返回\n");
getch();
WSACleanup( ); //卸载 Winsock 2 动态链接库Ws2_32.dll
return 0;
}
//----------------------------------------------------------------------
//下述函数加载初始化Winsock 2 动态链接库 Ws2_32.dll
bool InitSocket()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 0 ); //Wiinsock2.0版
err = WSAStartup( wVersionRequested, &wsaData ); //加载
if ( err != 0 ) { //没有Winsock 2 动态链接库 Ws2_32.dll
printf("没有Windows Socket动态库!\n");
getch();
return false;
}
if ( LOBYTE( wsaData.wVersion ) != 2 || //不是Winsock 2.0
HIBYTE( wsaData.wVersion ) != 0 ) {
printf("需要Windows Socket 2!\n");
getch();
WSACleanup( ); //卸载 Winsock 动态链接库
return false;
}
return true;
}
客户端程序:#pragma comment (lib, "Ws2_32.lib") //Winsock 2 函数库 //------------------------------------------------------------------------ #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <winsock2.h> //Winsock 2 函数头文件 //------------------------------------------------------------------------- bool InitSocket(); int main(int , char**) { int type; SOCKET sock; struct sockaddr addr; int len,portno; int err; char msg[255]; bool over; if( !InitSocket() ) return 0; //加载初始化 Winsock 2 动态链接库 Ws2_32.dll type = SOCK_STREAM; sock = socket( AF_INET,type,0 ); //创建客户端流套接口 if( sock==INVALID_SOCKET ){ //不能创建,返回 printf("不能创建Socket!"); getch(); WSACleanup( ); //卸载Winsock 2动态链接库Ws2_32.dll return 0; } // 以下输入对方服务器IP地址 ((sockaddr_in*)&addr)->sin_family = AF_INET; // Internet 协议 printf("输入服务器地址(x.x.x.x):"); gets(msg); ((sockaddr_in*)&addr)->sin_addr.s_addr = inet_addr(msg); // inet_addr()将点分十进制IP地址串转换为u_long类型 // 以下输入对方服务器端口号 printf("输入对方服务器端口号(3000):"); gets(msg); if(msg[0]==0x00) portno=3000; //如果直接回车,就采用默认端口号3000 else portno=atoi(msg); ((sockaddr_in*)&addr)->sin_port = htons( portno ); // htons():从短整数的主机字节顺序转换为网络字节顺序 // 以下与对方服务器连接 // 在使用面向连接协议 (TCP)时,必须与服务器连接成功后, // 才可通信;另外,若使用无连接的协议(UDP) ,则可以直 // 接向对方发数据、无需连接, 但面向连接收、发数据时用 // 的send()和recv()要换成无连接用的函数 sendto()和recvfrom() printf("与服务器连接...!"); len = sizeof(addr); err = connect( sock,(sockaddr*)&addr,len ); //连接 if( err==SOCKET_ERROR ){ //若连接失败
printf("连接失败!"); getch(); WSACleanup( ); //卸载Winsock 2动态链接库Ws2_32.dll return 0; } printf("成功连接到服务器!\n若输入bye则通信结束\n"); over = false; //状态设置为未结束 // 以下为客户与服务器会话交互,直至输入或收到bye,则 // 退出循环,结束 do{ printf("\n\n本方输入:"); gets(msg); if( strcmp(msg,"bye")==0 ) over = true; //输入"bye"则结束通信 send ( sock,msg,strlen(msg)+1,0); //发送信息 if(over) break; printf("等待服务器响应......\n"); len = recv ( sock,msg,200,0 ); //接收信息,接收缓冲区长200 msg[len]=0; //在接收串变量尾添结束符0 if( strcmp(msg,"bye")==0 ) over = true; //收到"bye"则结束通信 printf("对方回答:"); printf(msg); //显示接收信息 }while( !over ); //以下关闭套接口,卸载Winsock 2动态链接库 closesocket(sock); //关闭客户套接口 printf("\n会话结束,按任一键返回\n"); getch(); WSACleanup( ); //卸载Winsock 2动态链接库Ws2_32.dll return 0; } //--------------------------------------------------------------- //下述函数加载初始化Winsock 2 动态链接库 Ws2_32.dll bool InitSocket() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 0 ); //Wiinsock2.0版 err = WSAStartup( wVersionRequested, &wsaData ); //加载 if ( err != 0 ) { //没有Winsock 2 动态链接库 Ws2_32.dll printf("没有Windows Socket动态库!\n"); getch(); return false; } if ( LOBYTE( wsaData.wVersion ) != 2 || //不是Winsock 2.0 HIBYTE( wsaData.wVersion ) != 0 ) { printf("需要Windows Socket 2!\n"); getch(); WSACleanup( ); //卸载 Winsock 动态链接库 return false; }
} return true;
网络程序课程设计实验报告
专业:08计算机网络
姓名:
学号:v2008410 指导老师:辜希武
1
一、 实验目的
1、了解应用层和运输层的作用及相关协议的工作原理和机制。
2、掌握SOCKET 编程的基本方法。
二、 实验环境
1、Windows 操作系统
2、 C、C++编程开发环境(Microsoft Visual C++ 6.0)
三、实验要求
1、 基于Socket 编程
2、 提交实验设计报告和源代码;实验设计报告包括程序流程
3、 基于自己的实验设计报告,通过实验课的上机试验,在C++编程环境下将源代码编译
四、实验内容
题目一:
编写一个简单的基于控制台的Client/Server 通信程序,学习了解socket 编程的基本方法。程序功能为: 客户端向服务器端发送字符串,服务器接受并显示在服务器端窗口上 客户端可以指定服务器的IP 地址和端口 服务器显示接受到的字符串时要同时显示发送该字符 串的客户端地址和端口号
题目二:
编写一个基于控制台的聊天室程序,程序功能为: 服务器端首先建立聊天室,可以自由选择端口号 客户端输入服务器端的IP 地址和端口,然后登录到聊天室 客户在控制台输入的信息发送到服务器端 服务器端收到某客户端发来的信息后首先显示在屏幕上,并转发到其他聊天室客户端,并在其他客户端的控制台 上显示,显示格式为:【客户端IP 地址】:信息 当某客户离开聊天室后服务器能感知并发消息给其他客户端
题目三:
编写邮件客户端,功能要求如下: 客户端可以指定收件人地址,邮件主题,邮件正文并发送邮
件 客户点可以打开一个邮箱并显示邮箱里的邮件列表 客户端可以将邮件列表里的邮件下载到本地并显示
五、程序设计说明
1、主要模块:由Server和Client组成。在Server这一端初始化winsock、创建会话socket、bind一个端口、设置等待链接状态、连接并生成会话、调用send和recv、关闭socket。
2、模块功能:
初始化winsock:完成一系列初始化的工作。
创建会话socket:所有的通信在建立之前都要建一个socket。
bind一个端口:成功创建了一个socket后,用bind函数将socket和主机地址绑定。
设置等待链接状态:对于服务器的程序,当申请到socket,并将通信对象指定为inaddr_any之后,就应该等待一个客户机的程序来要求连接,listen函数就是把一个socket设置为这个状态。
连接并生成会话:accept函数从等待连接的队列中取第一个连接请求,并且创建一个新的socket来负责与客户端会话。
2
调用send和recv:sendto一般用于无连接的socket发送数据报文,报文的接受者由to参数指定。Recvfrom一般用于通过无连接的socket接收数据报文,报文的发送者由from参数指定。
关闭socket:关闭指定的socket。
3、程序主要流程图:
六、程序代码运行结果(部分源代码略)
1、服务器端执行结果
3
2、客户端执行结果
3、开多个客户端,利用多线程实现
4、邮件客户端程序winsock源代码:
#pragma once
#include "EmailClient.h" #include "base64.h"
#include <iostream>
using namespace std;
void SendMail(){
Client client; if(client.Init() == EXIT_FAILURE) return; //设置发件人地址、收件人地址 string from = "cnbluesky@163.com"; string to ="cnbluesky@163.com"; string responseFromServer; string commandToServer; string username = "cnbluesky"; string password = "cnbluesky"; string encodedUserName; string encodedPassword; //设置邮件正文
4
string mailContent = "From: " + from + "\n" + "To: " + to + "\n" + "Subject: " + "Test" + "\n" + "\n" + "This is a test email!"; //得到主机名 string localHostName = client.GetLocalHostName(); //接受服务器的应答 responseFromServer = client.RecvMsg(); //显示来自服务器的应答 cout << "MailServer:" + responseFromServer; //准备发送到服务器的命令
//EHLO 主机名
cout << "Client:" + commandToServer; //发送命令 client.SendMsg(commandToServer); // Sleep(1000); //接受服务器的应答 size_t found; do{ responseFromServer = client.RecvMsg(); //显示来自服务器的应答 cout << "MailServer:" + responseFromServer; found = responseFromServer.find("250 "); commandToServer = "EHLO " + localHostName + "\r\n"; }while(found == string::npos); //准备发送到服务器的命令 commandToServer = string("AUTH LOGIN") + "\r\n"; cout << "Client:" + commandToServer; //发送命令 client.SendMsg(commandToServer); //显示来自服务器的应答 cout << "MailServer:" + responseFromServer; //将用户名和密码进行base64编码 encodedUserName encodedPassword = = base64_encode(reinterpret_cast<const base64_encode(reinterpret_cast<const unsigned unsigned char char //AUTH LOGIN //接收服务器的应答 responseFromServer = client.RecvMsg(); *>(username.c_str()),username.length()); *>(password.c_str()),password.length()); //准备发送到服务器的命令 commandToServer = encodedUserName + "\r\n"; cout << "Client:" + commandToServer; //发送命令 client.SendMsg(commandToServer); //用户名 5
//接收服务器的应答
responseFromServer = client.RecvMsg();
//显示来自服务器的应答
cout << "MailServer:" + responseFromServer;
//准备发送到服务器的命令
commandToServer = encodedPassword + "\r\n";
cout << "Client:" + commandToServer;
//发送命令
client.SendMsg(commandToServer); //密码
//接收服务器的应答
responseFromServer = client.RecvMsg();
//显示来自服务器的应答
cout << "MailServer:" + responseFromServer;
//准备发送到服务器的命令
commandToServer = "MAIL FROM: <" + from + ">" + "\r\n"; cout << "Client:" + commandToServer;
//发送命令
client.SendMsg(commandToServer); //MAIL FROM: <发送信箱> //接收服务器的应答
responseFromServer = client.RecvMsg();
//显示来自服务器的应答
cout << "MailServer:" + responseFromServer;
//准备发送到服务器的命令
commandToServer = "RCPT TO: <" + to + ">" + "\r\n";
cout << "Client:" + commandToServer;
//发送命令
client.SendMsg(commandToServer); //RCPT TO: <接收信箱> //接收服务器的应答
responseFromServer = client.RecvMsg();
//显示来自服务器的应答
cout << "MailServer:" + responseFromServer;
//准备发送到服务器的命令
commandToServer = string("DATA") + "\r\n";
cout << "Client:" + commandToServer;
//发送命令
client.SendMsg(commandToServer); //DATA
//接收服务器的应答
responseFromServer = client.RecvMsg();
//显示来自服务器的应答
cout << "MailServer:" + responseFromServer;
//准备发送邮件正文
commandToServer = mailContent + "\r\n";
6
}
//发送命令 client.SendMsg(commandToServer); //邮件正文 commandToServer = string(".") + "\r\n"; client.SendMsg(commandToServer); client.SendMsg(commandToServer); //接收服务器的应答 responseFromServer = client.RecvMsg(); //显示来自服务器的应答 cout << "MailServer:" + responseFromServer; string input; do { cout << "\nPlease enter 'q' to quit:"; cin >> input; //结束标记"." commandToServer = string("QUIT") + "\r\n"; // QUIT }while(input != "q"); return;
七、实验心得:由于对编程的不熟悉,在编写代码的过程中问题很多,这样一份作业难度很大,不过
好的学习态度很重要。
7
信息与电气工程学院课程设计说明书20xx20xx学年第二学期课程名称网络工程课程设计题目校园网内网设计专业班级组长组员指导教师设计…
淮海工学院计算机工程学院课程设计报告设计名称:计算机网络课程设计姓名:学号:专业班级:系(院):设计时间:设计地点:网络技术室
武汉理工大学华夏学院课程设计报告书课程名称计算机网络课程设计题目小型互联网组网工程模拟系名专业班级姓名学号指导教师月日课程设计任务…
网络工程实践报告要求根据本课程的教学内容和下列要求设计一个网络方案的实施计划书希望结合实际体现目前较新和较成熟的网络技术体现其实用…
淮海工学院计算机工程学院课程设计报告设计名称计算机网络课程设计姓名学号专业班级系院计算机工程学院设计时间20xx010420xx0…
点对点数据交换P2P目录需求分析511课程设计目的512课程设计要求513选题与操作流程514开发环境与开发平台5总体设计521总…
课程设计报告专业班级姓名学号一实践内容1掌握RJ45网线接头的制作方法1双绞线的性能指标分类2RJ45接头线序各线的位置作用3制作…
天津职业技术师范大学1使用ARP发现局域网内活动主机发送ARP数据包摘要ARP协议用于完成IP地址与MAC地址之间的转换熟悉ARP…
长治学院课程设计报告课名称:计算机网络设计题目:一个简单企业网的设计与实现系别:计算机系专业:计算机科学与技术(1301班)组别:…
课程设计教学院课程名称题目专业班级姓名同组人员指导教师计算机学院计算机网络原理计算机网络原理计算机科学技术3班廖万君唐稳舟潘明磊兰…
实习报告因为考虑到以后毕业有可能从事这个行业的工作,因此我非常珍惜这次实习的机会,通过实习,了解现今社会所需求的人才,了解平面设计…