TCP服务器建立的步骤:
1. 调用socket建立TCP 套接字
2. 调用bind将套接字跟本地地址绑定
3. 调用listen建立监听
4. 建立accept接受来自客户端的连接,返回新的连接套接字
5. 在新的套接字上面,调用send/recv实现跟客户端的通信。
TCP 客户端建立的步骤:
1. 调用socket建立 TCP 套接字
2. 调用connect实现跟服务器端的连接
3. 调用send/recv实现跟服务器端的通信
无论是在服务器端还是客户端,要关闭连接,调用closesocket即可。
下面是练习的代码,当客户端成功连接到服务器端时,服务器端会打印出客户端的IP地址,会客户端发送过来的一段信息。
服务器代码:
- //启动服务器,参数一socket类型,参数二服务器绑定的IP地址
- bool ServerClass::StartServer(int Type,sockaddr_in sin)
- {
- SOCKET listen_socket= socket(AF_INET,Type,0);
- if (listen_socket==INVALID_SOCKET )
- {
- cout<<"服务器创建 监听 socket失败"<<endl;
- return false;
- }
- else
- {
- cout<<"服务器创建 监听 socket成功"<<endl;
- }
- int iRet=bind(listen_socket,(sockaddr *)&sin,sizeof(sin));
- if (iRet!=0)
- {
- cout<<"服务器 bind绑定失败"<<endl;
- return false;
- }
- else
- {
- cout<<"服务器 bind绑定成功"<<endl;
- }
- iRet=listen(listen_socket,SOMAXCONN);
- if (iRet!=0)
- {
- cout<<"服务器 listen 失败"<<endl;
- return false;
- }
- else
- {
- cout<<"服务器 listen 成功"<<endl;
- }
- sockaddr_in client_addr;
- SOCKET client_socket;
- int addr_len=sizeof(sockaddr_in);
- char dataBuffer[MAX_PATH]={0};
- while(true)
- {
- cout<<"服务器进入循环接受连接"<<endl;
- client_socket=accept(listen_socket,(sockaddr *)&client_addr,&addr_len);
- if (INVALID_SOCKET ==client_socket)
- {
- cout<<"accept接受连接失败"<<endl;
- }
- else
- {
- cout<<"accept接受连接成功,连接来自:"<<endl;
- cout<<inet_ntoa(client_addr.sin_addr)<<endl;
- recv(client_socket,dataBuffer,MAX_PATH,0);
- cout<<"收到信息:"<<dataBuffer<<endl;
- closesocket(client_socket);
- }
- }
- }
客户端代码:
- // 启动客户端
- bool ClientClass::StartClient(int Type, sockaddr_in addr)
- {
- SOCKET socket_client=socket(AF_INET,Type,0);
- if (socket_client==INVALID_SOCKET)
- {
- cout<<"客户端 创建 socket失败"<<endl;
- return false;
- }
- else
- {
- cout<<"客户端 创建 socket成功"<<endl;
- }
- int iRet=connect(socket_client,(sockaddr *)&addr,sizeof(sockaddr_in));
- if (iRet!=0)
- {
- cout<<"客户端 连接服务器 失败"<<endl;
- return false;
- }
- else
- {
- cout<<"客户端连接服务器成功"<<endl;
- }
- string strSend="Hello,I'm TanGaoWen";
- send(socket_client,(char *)strSend.c_str(),strSend.length(),0);
- //关闭socket连接
- closesocket(socket_client);
- return false;
- }
服务器的I/O模型是阻塞型的,如果需要处理来自多个客户端的连接,那么就必须开多个线程,一般一个线程处理一个来自客户端的连接。这样会消耗大量的系统资源,所以一般不采用阻塞的套接字管理模型。而是采用非阻塞的I/O 模型。以前写socket的时候,都是傻乎乎的给每个连接开个线程,这样服务器端根本就不能够承受大量的客户端的连接,是不太现实的。