C++网络编程之客户端程序

来源:互联网 发布:赛门铁克软件 编辑:程序博客网 时间:2024/05/21 10:08
#include<iostream>#include<WinSock2.h>using namespace std;#pragma comment(lib,"Ws2_32.lib")const int buf_len=1024;const int nDefaultServerPort=10000;//把用户在命令行输入的地址转换成整数地址,用户输入的地址可以有两种形式://点分十进制(192.168.1.123)和主机名称形式(localhost)u_long ResolveAddress(const char *szServer);//连接服务器//参数nServerAddr和nPort都必须是网络字节序SOCKET ConnectServer(u_long nServerAddr,int nPort);//处理回显业务逻辑bool ProcessConnection(SOCKET sd);bool ShutdownConnection(SOCKET sd);void DoWork(const char *szServer,int nPort);//客户端主题函数//命令行参数需要包含服务器地址和端口,如果用户没有输入端口,则使用默认的端口nDefaultServerPortint main(/*int argc,char *argv[]*/){/*if(argc<2){return -1;}const char *szServer=argv[1];int nPort=nDefaultServerPort;if(argc>=3){nPort=atoi(argv[2]);}*/char *szServer="localhost";int nPort=nDefaultServerPort;WSAData wsaData;int nCode;if((nCode=WSAStartup(MAKEWORD(2,2),&wsaData))!=0){cout<<"WSAStartup error"<<nCode<<endl;return -1;}DoWork(szServer,nPort);WSACleanup();return 0;}u_long ResolveAddress(const char *szServer){//首先尝试使用inet_addr来转换点分十进制地址,如果返回的是INADDR_NONE,则//表明szServer使用的是主机名称形式,此时需要调用gethostbyname来查询其地址u_long nAddr=inet_addr(szServer);if(nAddr==INADDR_NONE){hostent *ent=gethostbyname(szServer);if(ent==NULL){cout<<"gethostbyname error"<<WSAGetLastError()<<endl;}else{nAddr=*((u_long*)ent->h_addr_list[10]);}}if(nAddr==INADDR_NONE){cout<<"Error resolving address"<<endl;}return nAddr;}SOCKET ConnectServer(u_long nServerAddr,int nPort){//创建一个套接字SOCKET sd=socket(AF_INET,SOCK_STREAM,0);if(sd==INVALID_SOCKET){cout<<"socket error"<<WSAGetLastError()<<endl;return INVALID_SOCKET;}//填充服务器套接字地址sockaddr_in saServer;saServer.sin_family=AF_INET;saServer.sin_addr.s_addr=nServerAddr;saServer.sin_port=nPort;//调用connect 来连接到远程服务器if(connect(sd,(sockaddr*)&saServer,sizeof(sockaddr_in))==SOCKET_ERROR){cout<<"connect error"<<WSAGetLastError()<<endl;closesocket(sd);return INVALID_SOCKET;}return sd;}bool ProcessConnection(SOCKET sd){char buff[buf_len];//循环直至用户输入Ctrl+Zwhile(cin>>buff){int len=(int)strlen(buff);int nSent=0;//把用户的输入发送到服务器while(nSent<len){int nTemp=send(sd,&buff[nSent],len-nSent,0);if(nTemp>0){nSent+=nTemp;}else if(nTemp==SOCKET_ERROR){cout<<"send error"<<WSAGetLastError()<<endl;return false;}else{cout<<"Connection closed unexpectedly by peer"<<endl;return true;}}//接收服务器回显的数据。由于前面客户端发送了len个字节给服务器,因此//这里客户端必须从服务器接收len个字节int nRecv=0;while(nRecv<len){int nTemp=recv(sd,&buff[nRecv],len-nRecv,0);if(nTemp>0){nRecv+=nTemp;}else if(nTemp==SOCKET_ERROR){cout<<"recv error"<<WSAGetLastError()<<endl;return false;}else{cout<<"Connection closed unexpectedly by peer"<<endl;return true;}}//把服务器回显的数据输出到屏幕buff[nRecv]=0;cout<<buff<<endl;}return true;}void DoWork(const char *szServer,int nPort){//首先调用ResolveAddress来把用户输入的地址转换成整数地址u_long nServerAddr=ResolveAddress(szServer);if(nServerAddr==INADDR_NONE){return;}//第一阶段,连接服务器SOCKET sd=ConnectServer(nServerAddr,htons(nPort));if(sd==INVALID_SOCKET){return;}//第二阶段,处理回显业务逻辑if(ProcessConnection(sd)==true){//第三阶段,关闭连接ShutdownConnection(sd);}}bool ShutdownConnection(SOCKET sd){//首先发送一个TCP FIN分段,向对方表明已经完成数据发送if(shutdown(sd,SD_SEND)==SOCKET_ERROR){cout<<"shutdown error"<<WSAGetLastError()<<endl;return false;}char buff[buf_len];int nRecv;//继续接收对方的数据,直到recv返回0为止do{nRecv=recv(sd,buff,buf_len,0);if(nRecv==SOCKET_ERROR){cout<<"recv error"<<WSAGetLastError()<<endl;return false;}else if(nRecv>0){cout<<nRecv<<"unexpected bytes received"<<endl;}}while(nRecv!=0);if(closesocket(sd)==SOCKET_ERROR){cout<<"Closesocket error"<<WSAGetLastError()<<endl;return false;}return true;}

0 0
原创粉丝点击