一、TCP通信流程回顧
1. 服務器端流程
1. 創建Socket → socket()
2. 綁定地址和端口 → bind()
3. 開始監聽 → listen()
4. 接受客戶端連接 → accept()
5. 接收/發送數據 → recv()/send()
6. 關閉連接 → closesocket()
2. 客戶端流程
1. 創建Socket → socket()
2. 連接服務器 → connect()
3. 發送/接收數據 → send()/recv()
4. 關閉連接 → closesocket()
二、實現TCP服務器(Echo示例)?
1. 完整代碼
# include <iostream>
# include <winsock2.h>
# include <ws2tcpip.h>
# pragma comment ( lib, "ws2_32.lib" ) # include <ctype.h>
# include <limits.h> int main ( ) { WSADATA wsaData; if ( WSAStartup ( MAKEWORD ( 2 , 2 ) , & wsaData) != 0 ) { std:: cerr << "WSAStartup failed!" << std:: endl; return 1 ; } SOCKET serverSocket = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP) ; if ( serverSocket == INVALID_SOCKET) { std:: cerr << "Socket creation failed: " << WSAGetLastError ( ) << std:: endl; WSACleanup ( ) ; return 1 ; } sockaddr_in serverAddr; serverAddr. sin_family = AF_INET; inet_pton ( AF_INET, "127.0.0.1" , & ( serverAddr. sin_addr. s_addr) ) ; serverAddr. sin_port = htons ( 8080 ) ; if ( bind ( serverSocket, ( sockaddr* ) & serverAddr, sizeof ( serverAddr) ) == SOCKET_ERROR) { std:: cerr << "Bind failed: " << WSAGetLastError ( ) << std:: endl; closesocket ( serverSocket) ; WSACleanup ( ) ; return 1 ; } if ( listen ( serverSocket, SOMAXCONN) == SOCKET_ERROR) { std:: cerr << "Listen failed: " << WSAGetLastError ( ) << std:: endl; closesocket ( serverSocket) ; WSACleanup ( ) ; return 1 ; } std:: cout << "Server started. Listening on 127.0.0.1:8080..." << std:: endl; sockaddr_in clientAddr; int clientAddrLen = sizeof ( clientAddr) ; SOCKET clientSocket = accept ( serverSocket, ( sockaddr* ) & clientAddr, & clientAddrLen) ; if ( clientSocket == INVALID_SOCKET) { std:: cerr << "Accept failed: " << WSAGetLastError ( ) << std:: endl; closesocket ( serverSocket) ; WSACleanup ( ) ; return 1 ; } char buffer[ 1024 ] ; int bytesReceived; do { bytesReceived = recv ( clientSocket, buffer, sizeof ( buffer) , 0 ) ; if ( bytesReceived > 0 ) { send ( clientSocket, buffer, bytesReceived, 0 ) ; std:: cout << "Echoed " << bytesReceived << " bytes. Datas:" << std:: string ( buffer, bytesReceived) << std:: endl; } } while ( bytesReceived > 0 ) ; closesocket ( clientSocket) ; closesocket ( serverSocket) ; WSACleanup ( ) ; return 0 ;
}
三、實現TCP客戶端
1. 完整代碼
# include <iostream>
# include <string>
# include <winsock2.h>
# include <ws2tcpip.h>
# pragma comment ( lib, "ws2_32.lib" ) int main ( ) { WSADATA wsaData; if ( WSAStartup ( MAKEWORD ( 2 , 2 ) , & wsaData) != 0 ) { std:: cerr << "WSAStartup failed!" << std:: endl; return 1 ; } SOCKET clientSocket = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP) ; if ( clientSocket == INVALID_SOCKET) { std:: cerr << "Socket creation failed: " << WSAGetLastError ( ) << std:: endl; WSACleanup ( ) ; return 1 ; } sockaddr_in serverAddr; serverAddr. sin_family = AF_INET; inet_pton ( AF_INET, "127.0.0.1" , & ( serverAddr. sin_addr. s_addr) ) ; serverAddr. sin_port = htons ( 8080 ) ; if ( connect ( clientSocket, ( sockaddr* ) & serverAddr, sizeof ( serverAddr) ) == SOCKET_ERROR) { std:: cerr << "Connect failed: " << WSAGetLastError ( ) << std:: endl; closesocket ( clientSocket) ; WSACleanup ( ) ; return 1 ; } std:: cout << "Connected to server. Enter messages to send (type 'exit' to quit):" << std:: endl; std:: string message; char buffer[ 1024 ] ; do { std:: getline ( std:: cin, message) ; if ( message == "exit" ) break ; send ( clientSocket, message. c_str ( ) , message. size ( ) , 0 ) ; int bytesReceived = recv ( clientSocket, buffer, sizeof ( buffer) , 0 ) ; if ( bytesReceived > 0 ) { std:: cout << "Server echoed: " << std:: string ( buffer, bytesReceived) << std:: endl; } } while ( true ) ; closesocket ( clientSocket) ; WSACleanup ( ) ; return 0 ;
}
四、關鍵代碼解析
1. socket()
參數說明
AF_INET
:IPv4地址族。SOCK_STREAM
:面向流的傳輸協議(TCP)。IPPROTO_TCP
:明確指定TCP協議(可填0自動選擇)。
2. bind() 的地址設置
INADDR_ANY:若服務器需要監聽所有網卡,可改為:
serverAddr. sin_addr. s_addr = htonl ( INADDR_ANY) ;
3. listen()
的待處理隊列
SOMAXCONN
:系統允許的最大掛起連接數(Windows默認為200)。
4. accept()
的阻塞特性
若無客戶端連接,accept()會一直阻塞,直到新連接到達。
五、運行與測試
1. 客戶端輸入/輸出
2. 服務器端輸出