实验报告实验课程名称:通信软件基础实验课学院:软件工程学院专业:软件工程指导教师:报告人姓名:学号:班级:学期:实验成绩实验项目名称基于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#includestdafx.h#includeiostream.h#includestdio.h#includestring.h#includetime.h#includeWinSock2.h#includeWindows.h#includeserver.h#pragmacomment(lib,Ws2_32.lib)#pragmapack(1)//结构在存储时按字节对齐longTcpClientCount=0;intmain(intargc,char*argv[]){////检查命令行参数//if(argc!=2)//{//cerrWorngformat!\nCorrectusage:Server.exeTCPserverport;//return-1;//}//初始化winsock2环境WSADATAwsa;if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){cerr\nFailedtoinitializethewinsock2stack\nerrorcode:WSAGetLastError()endl;return-1;}//创建UDP服务器DWORDdwThreadId;CreateThread(NULL,0,UdpServer,NULL,0,&dwThreadId);//创建用于侦听的TCPServerSocketSOCKETListenSocket=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\nerrorcode:WSAGetLastError()endl;return-1;}//监听if((listen(ListenSocket,SOMAXCONN))==SOCKET_ERROR){cerr\nFailedtolistentheListenSocket\nerrorcode:WSAGetLastError()endl;return-1;}coutTCPServerStartedOnTCPPort:ListenPortendlendl;SOCKETTcpSocket;SOCKADDR_INTcpClientAddr;while(TRUE){//接受客户端连接请求intiSockAddrLen=sizeof(sockaddr);if((TcpSocket=accept(ListenSocket,(sockaddr*)&TcpClientAddr,&iSockAddrLen))==SOCKET_ERROR){cerr\nFailedtoaccepttheclientTCPSocket\nerrorcode:WSAGetLastError()endl;return-1;}//TCP线程数达到上限,停止接受新的Clientif(TcpClientCount=MAX_CLIENT){closesocket(TcpSocket);coutConnectionfromTCPclientinet_ntoa(TcpClientAddr.sin_addr):ntohs(TcpClientAddr.sin_port)refusedformaxclientnum\nendl;continue;}coutConnectionfromTCPclientinet_ntoa(TcpClientAddr.sin_addr):ntohs(TcpClientAddr.sin_port)accepted\nendl;TcpThreadParamParam;Param.socket=TcpSocket;Param.addr=TcpClientAddr;//创建TCP服务线程DWORDdwThreadId;CreateThread(NULL,0,TcpServeThread,&Param,0,&dwThreadId);InterlockedIncrement(&TcpClientCount);coutCurrentNumberofTCPClients:TcpClientCount'\n'endl;}closesocket(ListenSocket);WSACleanup();return0;}//TCP服务线程DWORDWINAPITcpServeThread(LPVOIDlpParam){charServerTCPBuf[MAX_BUF_SIZE];//获取线程参数SOCKETTcpSocket=((TcpThreadParam*)lpParam)-socket;SOCKADDR_INTcpClientAddr=((TcpThreadParam*)lpParam)-addr;//输出提示信息coutThread:GetCurrentThreadId()isservingclientfrominet_ntoa(TcpClientAddr.sin_addr):ntohs(TcpClientAddr.sin_port)endlendl;//发送端口号+STARTsprintf(ServerTCPBuf,%5d%s,UDPSrvPort,START_CMD);send(TcpSocket,ServerTCPBuf,strlen(ServerTCPBuf),0);coutWaitingforcommandfromClient(s)...endlendl;intTCPBytesReceived;time_tCurSysTime;while(TRUE){//读取client发来的请求命令:GETCURTIMEmemset(ServerTCPBuf,'\0',sizeof(ServerTCPBuf));TCPBytesReceived=recv(TcpSocket,ServerTCPBuf,sizeof(ServerTCPBuf),0);//TCPBytesReceived值为0表示client端已正常关闭连接//TCPBytesRecieved值为SOCKET_ERROR则表示socket的状态不正常,无法继续数据通讯//两种情况下都表明本线程的任务已结束,需要退出if(TCPBytesReceived==0||TCPBytesReceived==SOCKET_ERROR){coutClientfrominet_ntoa(TcpClientAddr.sin_addr):ntohs(TcpClientAddr.sin_port)disconnected.Thread:GetCurrentThreadId()isendingendlendl;break;}//检查收到的字符串是否为命令:GETCURTIMEif(strcmp(ServerTCPBuf,GETCURTIME_CMD)!=0){coutUnknowmcommandfromClientinet_ntoa(TcpClientAddr.sin_addr)endlendl;continue;}coutRequestforCurrenttimefromclientinet_ntoa(TcpClientAddr.sin_addr):ntohs(TcpClientAddr.sin_port)byTCPendlendl;//获取系统时间并发送给clienttime(&CurSysTime);memset(ServerTCPBuf,'\0',sizeof(ServerTCPBuf));strftime(ServerTCPBuf,sizeof(ServerTCPBuf),%Y-%m-%d%H:%M:%S,localtime(&CurSysTime));send(TcpSocket,ServerTCPBuf,strlen(ServerTCPBuf),0);coutServerCurrentTime:ServerTCPBuf'\n'endl;}InterlockedDecrement(&TcpClientCount);closesocket(TcpSocket);return0;}//UDP服务器线程DWORDWINAPIUdpServer(LPVOIDlpParam){charServerUDPBuf[MAX_BUF_SIZE];//UDPBufferSOCKADDR_INUDPClientAddr;//存储Client的地址信息//创建UDPserversocketSOCKETUDPSrvSocket=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_por