在坎坷路途中的第一个服务器端程序
能注释的地方我都注释了,因为才学2天,大家如果看到有什么地方有问题的请帮忙指出来。
// T2Server.cpp : 定义控制台应用程序的入口点。 // #include<iostream> #include<WinSock2.h> #pragma comment(lib,"WS2_32") using namespace std; #define REQUEST_BACKLOG 5 //如果想要使用SOCKET,WSAStartup函数必须要进行初始化才可以 bool initWSA(const WORD &wVersion ,WSADATA *wsadata) { int Ret = 0; if(Ret = WSAStartup(wVersion,wsadata)!=0) { cout<<"WSAStartup Error "<<Ret<<endl; return FALSE; } return true; } void cleanWSA() { if(WSACleanup() == SOCKET_ERROR) { cout<<"WSACleanup failed ,error"<<WSAGetLastError()<<endl; } } //这个是初始化服务器地址,包括IP地址和端口 void InitSockAddrByIP(SOCKADDR_IN *pSockAddr ,const char FAR*strIP,const INT &nPortID) { pSockAddr->sin_family = AF_INET; //htons这个不能忘了,网络字节序必须要转换,不然经常会出大问题 pSockAddr->sin_port = htons(nPortID); if(0!=strlen(strIP)) { pSockAddr->sin_addr.S_un.S_addr = inet_addr(strIP); // pSockAddr->sin_addr.S_un.S_addr = htonl(INADDR_ANY); cout<<inet_ntoa(pSockAddr->sin_addr)<<endl; //pSockAddr->sin_addr.s_addr = inet_addr(strIP); // pSockAddr->sin_addr.s_addr =htonl(inet_addr(strIP)); } else { pSockAddr->sin_addr.S_un.S_addr =htonl(INADDR_ANY); } } //将端口地址对象和sock对象进行绑定,也就是和后文的sock_listen对象 bool bindAddr(const SOCKADDR_IN * pSockAddr ,SOCKET pSocket) { int bindResult = bind(pSocket,(sockaddr*)(pSockAddr),sizeof(SOCKADDR_IN)); if(SOCKET_ERROR == bindResult) { cout<<"bind error : "<<WSAGetLastError()<<endl; return false; } else return true; } //这个是创建监听器,一旦有连接请求和发送信息的请求我们就能接收到了 bool SetListen(SOCKET s,int backlog) { int ListenResult = listen(s,backlog); if(SOCKET_ERROR == ListenResult) { cout<<"listen error"<<WSAGetLastError()<<endl; return false; } else return true; } int main() { WSADATA wsadata; if(!initWSA(MAKEWORD(2,2),&wsadata)) { return 0; } //指定连接IP地址和服务器端口 SOCKADDR_IN internetAddr; memset(&internetAddr, 0, sizeof(struct sockaddr_in)); char FAR *strIP ="192.168.1.101";//这个是服务器的IP地址 INT nPortID = 5150; InitSockAddrByIP(&internetAddr,strIP,nPortID); //创建listener_socket SOCKET listener_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(INVALID_SOCKET ==listener_socket) { cout<<"listener_socket creat failed"<<endl; return 0; } if(!bindAddr(&internetAddr,listener_socket)) return 0; if (!SetListen(listener_socket, REQUEST_BACKLOG ) ) { return 0; } cout<<"server started ~~~"<<endl; //创建socket保存结构 fd_set fdSocket; FD_ZERO(&fdSocket); FD_SET(listener_socket,&fdSocket); //查找可读的socket while(1) { //这个只是一个缓冲对象 fd_set fdSocket_temp; FD_ZERO(&fdSocket_temp); fdSocket_temp = fdSocket; //这个是读用的 fd_set fdRead; FD_ZERO(&fdRead); fdRead = fdSocket; //这个是catch错误用的 fd_set fdExceptds; FD_ZERO(&fdExceptds); fdExceptds = fdSocket; //除了第一个参数,第二个参数是读fd_set对象,第三个参数是写fd_set对象,第四个参数是catch错误的fd_set对象 int nResult_select = select(0,&fdRead,NULL,&fdExceptds,NULL); //这个时候表示有消息了 if(0 <nResult_select) { int socket_count = fdSocket_temp.fd_count; for(int i =0;i<socket_count;i++) { //如果现在fdRead里有消息传来 if(FD_ISSET(fdSocket_temp.fd_array[i],&fdRead)) { if(fdSocket_temp.fd_array[i]==listener_socket) //如果是当前正在监听的表示这个还未接受连接,那我们就接下来连接就好了,其他的已经连接上的就接收信息就好了 { if(fdSocket.fd_count<FD_SETSIZE) { //接受这个新的连接 SOCKADDR_IN ClientAddr; int addrlen = static_cast<int>(sizeof(ClientAddr)); //一定要赋值 SOCKET newClient_SOCKET = accept(listener_socket,(sockaddr *)&ClientAddr,&addrlen); cout<<inet_ntoa(ClientAddr.sin_addr)<<endl; if(INVALID_SOCKET==newClient_SOCKET) { cout<<"accep error "<<WSAGetLastError()<<endl; } else { FD_SET(newClient_SOCKET,&fdSocket); cout<<"add new connect"<<endl; } } else { cout<<"too much connecttion"<<endl; } } //已经连接上了的我们就直接接收数据好了 else { char recvbuff[1024]; int ret = 0; ret = recv(fdSocket_temp.fd_array[i],recvbuff,static_cast<int>(strlen(recvbuff)),0); if(ret>0) { recvbuff[ret]='\0'; cout<<"recv: "<<recvbuff<<endl; //回复给客户端 char backbuf[1024]="recevie OK"; send( fdSocket_temp.fd_array[i], backbuf, static_cast<int>( strlen(backbuf) ), 0 ); } else //此时ret返回值为0 { //连接已经断开了。断开有很短原因 closesocket(fdSocket_temp.fd_array[i]); //在fd_set中去掉这个连接 FD_CLR(fdSocket_temp.fd_array[i],&fdSocket ); } } } //既然没有发送消息又占用了连接的位置,我们就释放他来控制空闲的空间 else if(fdSocket_temp.fd_array[i] != listener_socket ) { //该连接断开 closesocket( fdSocket_temp.fd_array[i] ); FD_CLR( fdSocket_temp.fd_array[i], &fdSocket ); } //如果Catch到了错误 if(FD_ISSET(fdSocket_temp.fd_array[i],&fdExceptds)&& (fdSocket_temp.fd_array[i] != listener_socket) ) { //该连接断开 closesocket( fdSocket_temp.fd_array[i] ); FD_CLR( fdSocket_temp.fd_array[i], &fdSocket ); } } } else if( SOCKET_ERROR ==nResult_select ) { cout << "select error : " << WSAGetLastError() << endl; return 0; } Sleep(50);//这个必须要,不然死循环一直弄下去机子可能会死去。。 } closesocket(listener_socket); cleanWSA(); return 0; }