UDP及TCP通信程序的设计与实现实验报告.doc
- 文档编号:1227904
- 上传时间:2023-04-30
- 格式:DOC
- 页数:17
- 大小:523.50KB
UDP及TCP通信程序的设计与实现实验报告.doc
《UDP及TCP通信程序的设计与实现实验报告.doc》由会员分享,可在线阅读,更多相关《UDP及TCP通信程序的设计与实现实验报告.doc(17页珍藏版)》请在冰点文库上搜索。
计算机网络实验报告
实验报告
课程计算机网络(双语)(课程设计)
实验名称UDP及TCP通信程序的设计与实现
专业班级
姓名
学号
2013年5月30日
16
目录
实验目的和内容 1
实验目的 1
实验内容 1
实验环境 2
程序的逻辑框图 2
UDP通信程序的逻辑框图:
2
TCP通信程序的逻辑框图:
3
程序源代码(数据结构的描述、核心算法) 4
1.TCP通信程序源代码 4
2.TCP通信程序数据结构的描述 7
3.TCP通信程序的核心算法 7
4.UDP通信程序源代码 8
5.UDP通信程序数据结构的描述 11
6.UDP通信程序的核心算法 12
实验数据、结果分析 13
TCP通信程序实验结果分析 13
UDP通信程序实验结果分析 14
总结 16
实验目的和内容
实验目的
掌握win32平台下,使用winsockAPI来实现UDP通信程序和TCP通信程序。
实验内容
1.实现控制台模式下,在单机上基于UDP的聊天程序;
2.实现控制台模式下,在单机上基于TCP的聊天程序;
3.上述两个程序,最简单的实现方式是:
一方发送、另一方接收、交替进行;
4.提交上述2个程序的源程序,程序代码有充分的注释,并填写实验报告,实验报告的主要内容为说明程序设计的思路,程序代码的流程。
实验环境
在win7系统下,visualstudio2008环境下的win32平台下
程序的逻辑框图
UDP通信程序的逻辑框图:
TCP通信程序的逻辑框图:
程序源代码(数据结构的描述、核心算法)
1.TCP通信程序源代码
Client端:
#include"stdafx.h"
#include
#include
#include
#include
//初始化函数,初始化版本号
intInitSock(BYTEminorVer=2,BYTEmajorVer=2)
{
WSADATAwsaData;
WORDsockVersion=MAKEWORD(minorVer,majorVer);
if(WSAStartup(sockVersion,&wsaData)!
=0)
exit(0);
return1;
}
intmain()
{
charrbuf[256];
charszText[256];
InitSock();
//创建socket,第一个参数表示用IP协议,第二个参数表示用TCP传输,第三个不大清楚
SOCKETsListen=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//判断socket是否创建成功
if(sListen==INVALID_SOCKET)
{
printf("Failedsocket()\n");
return0;
}
//用于存储IP地址和端口号的变量
sockaddr_insin;
sin.sin_family=AF_INET; //IP协议
sin.sin_port=htons(4567); //端口号
sin.sin_addr.S_un.S_addr=INADDR_ANY;//接收任何IP的连接
//绑定函数,将socket与IP地址和端口绑定在一块
if(bind(sListen,(LPSOCKADDR)&sin,sizeof(sin))==SOCKET_ERROR)
{
printf("Failedbind()\n");
return0;
}
//开始监听,第二个参数表示最大连接数
if(listen(sListen,2)==SOCKET_ERROR)
{
printf("Failedlisten()\n");
return0;
}
//定义一个新的变量
sockaddr_inremoteAddr;
intnAddrLen=sizeof(remoteAddr);
//用于存储连接客户端的socket
SOCKETsClient;
//accept函数会阻塞,直到等到有socket连接服务器为止,才继续往后执行,并将客户端的IP和端口号存在remoteAddr中
sClient=accept(sListen,(SOCKADDR*)&remoteAddr,&nAddrLen);
printf("接收到一个连接%s\r\n",inet_ntoa(remoteAddr.sin_addr));
while(TRUE)
{
if(sClient==INVALID_SOCKET)
{
printf("Failedaccept()");
continue;
}
printf("send:
");
scanf("%s",szText);
//发送函数,往sClient这个socket中发送szText
send(sClient,szText,strlen(szText),0);
//recv为阻塞函数,等待sClient中传来数据
intnRecv=recv(sClient,rbuf,256,0);
if(nRecv>0)
{
rbuf[nRecv]='\0';
printf("receive:
%s\n",rbuf);
}
}
closesocket(sClient);
closesocket(sListen);
WSACleanup();
return0;
}
Server端:
#include"stdafx.h"
#include
#include
#include
#include
//初始化函数,初始化版本号
intInitSock(BYTEminorVer=2,BYTEmajorVer=2)
{
WSADATAwsaData;
WORDsockVersion=MAKEWORD(minorVer,majorVer);
if(WSAStartup(sockVersion,&wsaData)!
=0)
exit(0);
return1;
}
intmain()
{
InitSock();
//创建socket,第一个参数表示用IP协议,第二个参数表示用TCP传输,第三个不大清楚
SOCKETs=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s==INVALID_SOCKET)
{
printf("Failedsocket()\n");
return0;
}
//用于存储IP地址和端口号的变量
sockaddr_inservAddr;
servAddr.sin_family=AF_INET;
servAddr.sin_port=htons(4567); //要连接的端口号
servAddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//要连接的IP地址
//连接函数,是一个阻塞类型的函数,用s这个socket与服务器地址的某个端口连接,之后往s这个socket中写数据,服务器就能收到
if(connect(s,(sockaddr*)&servAddr,sizeof(servAddr))==-1)
{
printf("Failedconnect()\n");
return0;
}
charbuff[256];
charszText[256];
while(true){
//接收函数,是一个阻塞类型的函数,等待s这个socket中传来数据,256表示接收的最大字符数
intnRecv=recv(s,buff,256,0);
if(nRecv>0)
{
buff[nRecv]='\0';
printf("receive:
%s\n",buff);
}
printf("send:
");
scanf("%s",szText);
//发送函数,往s这个socket中发送szText这个字符串
send(s,szText,strlen(szText),0);
}
closesocket(s);
WSACleanup();
return0;
}
2.TCP通信程序数据结构的描述
(1)客户端及服务器都含有存储IP地址及端口号的数据结构,sockaddr_inremoteAddr;和servAddr
(2)用于存储连接客户端的socket:
SOCKETsClient;和用于存储连接服务器的socket:
SOCKETs
3.TCP通信程序的核心算法
服务器首先启动,通过调用socket()建立一个套接口,然后bind()将该套接口和本地地址(IP地址和端口)联系在一起,再listen()使套接口做好侦听的准备,并规定它的请求队列的长度,之后就调用accept()来接收连接,并获得客户机的地址信息;客户在建立套接口后就可调用connect()和服务器建立连接;连接一旦建立,客户机和服务器之间就可以通过调用:
send()和recv()(或read()和write())来发送和接收数据;最后,待数据传送结束后,双方调用closesocket()关闭套接口。
4.UDP通信程序源代码
Client端:
#include"stdafx.h"
#include
#include
#include
//在同一主机的不同端口上分别运行服务器程序和客户端程序
WORDRPort=6666;//远程端口RemotePort
charRIP[16]="127.0.0.1";//远程IP地址RemoteIPAddr
WORDLPort=7777;//本地端口LocalPort
charLIP[16]="127.0.0.1";//本地IP地址LocalIPAddr
SOCKETS;//套接口SOCKET
structsockaddr_inrAddr;//远程参数,remoteAddr
structsockaddr_inlAddr;//本地参数,localAddr
WSADATAWD;//WinsockDLL信息
intr;//result;
//-----------------------------------------------
voidShowInfo(char*info){
puts(info);
exit
(1);
}
//-----------------------------------------------
voidSetsockAddr(structsockaddr_in*A,WORDPort,char*IP){
A->sin_family=AF_INET;//TCP/IP协议
A->sin_port=htons(Port);//端口
A->sin_addr.s_addr=inet_addr(IP);//IP地址
}
//------------------------------------------------
voidmain(){
WORDv;//wVersionRequested;
//---------StartupWinsocket--------
v=0x0101;//0x0101forv1.1,0x0002forv2.0
r=WSAStartup(v,(LPWSADATA)&WD);
if(r!
=0)
ShowInfo("Start_Error");
//---------CreateWinsocket--------
S=socket(AF_INET,SOCK_DGRAM,0);//创建套接字
if(S==-1)
ShowInfo("socket_Create_Error");
intl=sizeof(rAddr);
charMsg[80];
puts("TypeexitthenQuitProgram!
");
SetsockAddr(&lAddr,LPort,LIP);//初始化变量lAddr
r=bind(S,(structsockaddrfar*)&lAddr,sizeof(lAddr));
if(r==-1)
ShowInfo("bind_Error");
SetsockAddr(&rAddr,RPort,RIP);
do{
//---------SendMess--------
puts("Send:
");
gets(Msg);
if(!
strcmp(Msg,"exit"))//
break;
r=sendto(S,Msg,strlen(Msg),0,(structsockaddrfar*)&rAddr,l);//通过套接字向接收端发送信息
if(r==-1)
ShowInfo("Send_Error");
//---------RecieveMess--------
puts("Sendok!
WaitingRecieve...");
// r=recv(S,Msg,80,0);
r=recvfrom(S,Msg,80,0,(structsockaddrfar*)&rAddr,&l);//
//发送套接口的主机地址信息存放在rAddr中
if(r==-1)
ShowInfo("Recieve_Error");
Msg[r]=0;
puts(Msg);
puts("Recieveok!
");
}while
(1);
closesocket(S);
WSACleanup();
return;
Server端:
#include"stdafx.h"
#include
#include
#include
//在同一主机的不同端口上分别运行服务器程序和客户端程序
WORDRPort=7777;//远程端口RemotePort
charRIP[16]="127.0.0.1";//远程IP地址RemoteIPAddr
WORDLPort=6666;//本地端口LocalPort
charLIP[16]="127.0.0.1";//本地IP地址LocalIPAddr
SOCKETS;//套接口SOCKET
structsockaddr_inrAddr;//远程参数,remoteAddr
structsockaddr_inlAddr;//本地参数,localAddr
WSADATAWD;//WinsockDLL信息
intr;//result;
//-----------------------------------------------
voidShowInfo(char*info){
puts(info);
exit
(1);
}
//-----------------------------------------------
voidSetsockAddr(structsockaddr_in*A,WORDPort,char*IP){
A->sin_family=AF_INET;//TCP/IP协议
A->sin_port=htons(Port);//端口
A->sin_addr.s_addr=inet_addr(IP);//IP地址
}
//------------------------------------------------
voidmain(){
WORDv;//wVersionRequested;
//---------StartupWinsocket--------
v=0x0101;//0x0101forv1.1,0x0002forv2.0
r=WSAStartup(v,(LPWSADATA)&WD);
if(r!
=0)
ShowInfo("Start_Error");
//---------CreateWinsocket--------
S=socket(AF_INET,SOCK_DGRAM,0);//创建套接字
if(S==-1)
ShowInfo("socket_Create_Error");
intl=sizeof(rAddr);
charMsg[80];
puts("TypeexitthenQuitProgram!
");
SetsockAddr(&lAddr,LPort,LIP);//初始化变量lAddr
r=bind(S,(structsockaddrfar*)&lAddr,sizeof(lAddr));
if(r==-1)
ShowInfo("bind_Error");
SetsockAddr(&rAddr,RPort,RIP);
do{
//---------RecieveMess--------
//puts("Sendok!
WaitingRecieve...");
//r=recv(S,Msg,80,0);
r=recvfrom(S,Msg,80,0,(structsockaddrfar*)&lAddr,&l);//发送套接口的主机地址信息存放在rAddr中
if(r==-1)
ShowInfo("Recieve_Error");
Msg[r]=0;
puts(Msg);
puts("Recieveok!
");
//---------SendMess--------
puts("Send:
");
gets(Msg);
if(!
strcmp(Msg,"exit"))//
break;
r=sendto(S,Msg,strlen(Msg),0,(structsockaddrfar*)&lAddr,l);//通过套接字向接收端发送信息
if(r==-1)
ShowInfo("Send_Error");
}while
(1);
closesocket(S);
WSACleanup();
return;
}
5.UDP通信程序数据结构的描述
(1)SOCKETS:
服务器套接字
(2)structsockaddr_inrAddr:
远程参数,remoteAddr,存储TCP/IP协议,IP地址及端口号
(3)structsockaddr_inlAddr:
本地参数,localAddr,存储TCP/IP协议,IP地址及端口号
6.UDP通信程序的核心算法
服务器首先启动,通过调用socket()建立一个套接口,然后bind()将该套接口和本地地址(IP地址和端口)联系在一起,服务器调用recvfrom()等待接收数据。
客户机通过调用socket()建立一个套接口,然后bind()将该套接口和本地地址(IP地址和端口)联系在一起,客户机调用sendto()向服务器发送数据;
服务器的recvfrom()接收到客户机的数据后,调用sendto()向客户机发送应答数据;
客户机的recvfrom()便接收到了服务器的应答数据;
最后,待数据传送结束后,双方调用closesocket()关闭套接口。
关于程序中调用的库函数的几点说明:
1.对sendto函数的说明
intsendto(
SOCKETs,//源套接口
char*buf,//待发送数据的缓冲区
intbuflen,//缓冲区中数据的长度
intflags,//调用方式标志位,一般取0
structsockaddrFAR*to,//指向目的套接口的主机地址
inttolen//目的套接口主机地址的长度
);
sendto函数主要用于SOCK_DGRAM类型套接口向to参数指定端的套接口发送数据报。
对于SOCK_STREAM类型套接口,to和tolen参数被忽略;这种情况下sendto()等价于send()。
2.对recvfrom函数的说明
intrecvfrom(
SOCKETs//接收套接口
char*buf//接收数据的缓冲区
intlen//缓冲区中数据的长度
intflags//调用方式标志位,一般取0
structsockaddrFAR*from//获取发送套接口的主机地址
intfromlen//发送套接口的主机地址的长度
);
recvfrom函数主要用于从一个套接口接收数据
实验数据、结果分析
TCP通信程序实验结果分析:
当Client端启动时,Server端收到来自Client端的信号,表明双方的连接已经建立,可以互相通讯,从client端发送“hello”,Server端收到来自Client端的“hello”,Server端也可以向client端发送信息。
UDP通信程序实验结果分析:
打开UDP的client端,并打开UDP的server端,发送“hello”给
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- UDP TCP 通信 程序 设计 实现 实验 报告