基于WinSock的简单TCP网络编程实验报告.docx
《基于WinSock的简单TCP网络编程实验报告.docx》由会员分享,可在线阅读,更多相关《基于WinSock的简单TCP网络编程实验报告.docx(18页珍藏版)》请在冰豆网上搜索。
基于WinSock的简单TCP网络编程实验报告
实验报告
实验课程名称:
通信软件基础实验课
学院:
软件工程学院
专业:
软件工程
指导教师:
报告人姓名:
学号:
班级:
学期:
实验
成绩
实验项目名称
基于WinSock的简单TCP网络编程
一、实验目的与要求:
1、学习和掌握Socket编程的面向连接编程模型。
2、学习和掌握基于WinSock的TCP网络编程方法。
二、实验设备及软件:
笔记本电脑、Window7操作系统、MicrosoftVisualStudio2012
三、实验方法(原理、流程图)
流程图:
四、实验过程、步骤及内容
实验代码:
server.h
#defineMAX_CLIENT10//同时服务的client数目上限
#defineMAX_BUF_SIZE65535//缓存区的大小
constu_shortUDPSrvPort=2345;//Server的UDP端口
constcharSTART_CMD[]="START";
constcharGETCURTIME_CMD[]="GETCURTIME";
//传递给TCP线程的结构化参数
structTcpThreadParam
{
SOCKETsocket;
sockaddr_inaddr;
};
DWORDWINAPITcpServeThread(LPVOIDlpParam);//TCP线程的线程函数
DWORDWINAPIUdpServer(LPVOIDlpParam);//UDP服务器线程
server.cpp
#include"stdafx.h"
#include"iostream.h"
#include"stdio.h"
#include"string.h"
#include"time.h"
#include"WinSock2.h"
#include"Windows.h"
#include"server.h"
#pragmacomment(lib,"Ws2_32.lib")
#pragmapack
(1)//结构在存储时按字节对齐
longTcpClientCount=0;
intmain(intargc,char*argv[])
{
////检查命令行参数
//if(argc!
=2)
//{
//cerr<<"Worngformat!
\nCorrectusage:
Server.exe";
//return-1;
//}
//初始化winsock2环境
WSADATAwsa;
if(WSAStartup(MAKEWORD(2,2),&wsa)!
=0)
{
cerr<<"\nFailedtoinitializethewinsock2stack\n"
<<"errorcode:
"<return-1;
}
//创建UDP服务器
DWORDdwThreadId;
CreateThread(NULL,0,UdpServer,NULL,0,&dwThreadId);
//创建用于侦听的TCPServerSocket
SOCKETListenSocket=socket(AF_INET,SOCK_STREAM,0);
//获取TCP监听端口号
u_shortListenPort=(u_short)atoi(argv[1]);
//获取本机名
charhostname[256];
gethostname(hostname,sizeof(hostname));
//获取本地IP地址
hostent*pHostent=gethostbyname(hostname);
//填充本地TCPSocket地址结构
SOCKADDR_INListenAddr;
memset(&ListenAddr,0,sizeof(SOCKADDR_IN));
ListenAddr.sin_family=AF_INET;
ListenAddr.sin_port=htons(ListenPort);
ListenAddr.sin_addr=*(in_addr*)pHostent->h_addr_list[0];
//绑定TCP端口
if(bind(ListenSocket,(sockaddr*)&ListenAddr,sizeof(ListenAddr))==SOCKET_ERROR)
{
cerr<<"\nFailedtobindtheListenSocket\n"
<<"errorcode:
"<return-1;
}
//监听
if((listen(ListenSocket,SOMAXCONN))==SOCKET_ERROR)
{
cerr<<"\nFailedtolistentheListenSocket\n"
<<"errorcode:
"<return-1;
}
cout<<"TCPServerStartedOnTCPPort:
"<SOCKETTcpSocket;
SOCKADDR_INTcpClientAddr;
while(TRUE)
{
//接受客户端连接请求
intiSockAddrLen=sizeof(sockaddr);
if((TcpSocket=accept(ListenSocket,(sockaddr*)&TcpClientAddr,&iSockAddrLen))==SOCKET_ERROR)
{
cerr<<"\nFailedtoaccepttheclientTCPSocket\n"
<<"errorcode:
"<return-1;
}
//TCP线程数达到上限,停止接受新的Client
if(TcpClientCount>=MAX_CLIENT)
{
closesocket(TcpSocket);
cout<<"ConnectionfromTCPclient"<"<continue;
}
cout<<"ConnectionfromTCPclient"<"<TcpThreadParamParam;
Param.socket=TcpSocket;
Param.addr=TcpClientAddr;
//创建TCP服务线程
DWORDdwThreadId;
CreateThread(NULL,0,TcpServeThread,&Param,0,&dwThreadId);
InterlockedIncrement(&TcpClientCount);
cout<<"CurrentNumberofTCPClients:
"<}
closesocket(ListenSocket);
WSACleanup();
return0;
}
//TCP服务线程
DWORDWINAPITcpServeThread(LPVOIDlpParam)
{
charServerTCPBuf[MAX_BUF_SIZE];
//获取线程参数
SOCKETTcpSocket=((TcpThreadParam*)lpParam)->socket;
SOCKADDR_INTcpClientAddr=((TcpThreadParam*)lpParam)->addr;
//输出提示信息
cout<<"Thread:
"<"<//发送端口号+"START"
sprintf(ServerTCPBuf,"%5d%s",UDPSrvPort,START_CMD);
send(TcpSocket,ServerTCPBuf,strlen(ServerTCPBuf),0);
cout<<"WaitingforcommandfromClient(s)..."<intTCPBytesReceived;
time_tCurSysTime;
while(TRUE)
{
//读取client发来的请求命令:
"GETCURTIME"
memset(ServerTCPBuf,'\0',sizeof(ServerTCPBuf));
TCPBytesReceived=recv(TcpSocket,ServerTCPBuf,sizeof(ServerTCPBuf),0);
//TCPBytesReceived值为0表示client端已正常关闭连接
//TCPBytesRecieved值为SOCKET_ERROR则表示socket的状态不正常,无法继续数据通讯
//两种情况下都表明本线程的任务已结束,需要退出
if(TCPBytesReceived==0||TCPBytesReceived==SOCKET_ERROR)
{
cout<<"Clientfrom"<"<"<break;
}
//检查收到的字符串是否为命令:
"GETCURTIME"
if(strcmp(ServerTCPBuf,GETCURTIME_CMD)!
=0)
{
cout<<"UnknowmcommandfromClient"<continue;
}
cout<<"RequestforCurrenttimefromclient"<"<//获取系统时间并发送给client
time(&CurSysTime);
memset(ServerTCPBuf,'\0',sizeof(ServerTCPBuf));
strftime(ServerTCPBuf,sizeof(ServerTCPBuf),"%Y-%m-%d%H:
%M:
%S",localtime(&CurSysTime));
send(TcpSocket,ServerTCPBuf,strlen(ServerTCPBuf),0);
cout<<"ServerCurrentTime:
"<}
InterlockedDecrement(&TcpClientCount);
closesocket(TcpSocket);
return0;
}
//UDP服务器线程
DWORDWINAPIUdpServer(LPVOIDlpParam)
{
charServerUDPBuf[MAX_BUF_SIZE];//UDPBuffer
SOCKADDR_INUDPClientAddr;//存储Client的地址信息
//创建UDPserversocket
SOCKETUDPSrvSocket=socket(AF_INET,SOCK_DGRAM,0);
//获取本机名
charhostname[256];
gethostname(hostname,sizeof(hostname));
//获取本地IP地址
hostent*pHostent=gethostbyname(hostname);
//填充本地UDPSocket地址结构
SOCKADDR_INUDPSrvAddr;
memset(&UDPSrvAddr,0,sizeof(SOCKADDR_IN));
UDPSrvAddr.sin_family=AF_INET;
UDPSrvAddr.sin_port=htons(UDPSrvPort);
UDPSrvAddr.sin_addr=*(in_addr*)pHostent->h_addr_list[0];
//绑定UDP端口
if(bind(UDPSrvSocket,(sockaddr*)&UDPSrvAddr,sizeof(UDPSrvAddr))==SOCKET_ERROR)
{
cerr<<"bind()failedforUDPSrvSocket\n"
<<"errorcode:
"<return-1;
}
cout<<"UDPServerStartedOnUDPPort:
"<while(TRUE)
{
memset(ServerUDPBuf,'\0',sizeof(ServerUDPBuf));
//接收UDP请求
intiSockAddrLen=sizeof(sockaddr);
if((recvfrom(UDPSrvSocket,ServerUDPBuf,sizeof(ServerUDPBuf),0,(sockaddr*)&UDPClientAddr,&iSockAddrLen))==SOCKET_ERROR)
{
cerr<<"recvfrom()failedforUDPSrvSocket\n"
<<"errorcode:
"<continue;
}
cout<<"ClientCommand:
Echo\n\n";
cout<<"\""<"<//ECHO
iSockAddrLen=sizeof(sockaddr);
if((sendto(UDPSrvSocket,ServerUDPBuf,strlen(ServerUDPBuf),0,(sockaddr*)&UDPClientAddr,iSockAddrLen))==SOCKET_ERROR)
{
cerr<<"sendto()failedforUDPSrvSocket\n"
<<"errorcode:
"<continue;
}
cout<<"Echo"<<"\""<"<}
return0;
}
client.exe
#include"stdafx.h"
#include"WinSock2.h"
#include"iostream.h"
#include"stdio.h"
#pragmacomment(lib,"Ws2_32.lib")
#defineMAX_BUF_SIZE65535
charClientBuf[MAX_BUF_SIZE];
constcharSTART_CMD[]="START";
constcharGETCURTIME_CMD[]="GETCURTIME";
//输出用户选择界面
voidUserPrompt()
{
cout<<"InputthecorrespondingNumtoselectwhatyouwanttheprogramtodo"<<<"\t1.Getcurrenttime(TCP)"<<<"\t2.EchoMode(UDP)"<<<"\t3.Exittheprogram"<<<"EnterYourchoice:
";
}
intmain(intargc,char*argv[])
{
unsignedshortServerUDPPort;
SOCKETcTCPSocket,cUDPSocket;
WSADATAwsadata;
SOCKADDR_INTCPServer,UDPServer,RecvFrom;
intRecvFromLength=sizeof(RecvFrom);
charUserChoice;
charportnum[5];
unsignedlongBytesReceived,BytesSent;
intRetValue;
//检查命令行参数
if(argc!
=3)
{
cout<<"Worngformat!
"<Client.exe"<return1;
}
u_longServerIP=inet_addr(argv[1]);
u_shortServerTCPPort=(u_short)atoi(argv[2]);
//初始化winsock库
if((RetValue=WSAStartup(MAKEWORD(2,2),&wsadata))!
=0)
{
printf("WSAStartup()failedwitherror%d\n",RetValue);
return2;
}
//创建TCPSocket
if((cTCPSocket=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
{
printf("WSASocket()forcTCPSocketfailedwitherror%d\n",WSAGetLastError());
return3;
}
//创建UDPSocket
if((cUDPSocket=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
{
printf("WSASocket()forcUDPSocketfailedwitherror%d\n",WSAGetLastError());
return4;
}
TCPServer.sin_family=AF_INET;
TCPServer.sin_port=htons(ServerTCPPort);
TCPServer.sin_addr.S_un.S_addr=ServerIP;
//通过TCPSocket连接server
if((RetValue=WSAConnect(cTCPSocket,(sockaddr*)&TCPServer,sizeof(TCPServer),NULL,NULL,NULL,NULL))==SOCKET_ERROR)
{
printf("WSAConnect()failedforcTCPSocketwitherror%d\n",WSAGetLastError());
printf("Can'tconnecttoserver.\n");
return5;
}
//与server建立连接后读取Server发送过来的ServerUDP端口和"START"
BytesReceived=recv(cTCPSocket,ClientBuf,sizeof(ClientBuf),0);
if(BytesReceived==0||BytesReceived==SOCKET