本文共 4330 字,大约阅读时间需要 14 分钟。
网络进程间通信是计算机科学中的一个基础问题,socket作为实现网络通信的核心工具,在现代网络应用中无处不在。本文将从网络通信的基本原理出发,深入探讨socket的工作机制及其在TCP协议中的应用。
在网络环境中,进程间通信需要唯一标识每个进程。TCP/IP协议族通过三元组(IP地址、协议、端口)实现这一点:IP地址唯一标识网络中的主机,而协议和端口则唯一标识主机中的应用程序。这种标识机制使得网络中的进程通信变得可能。
在Unix系统中,socket提供了一种统一的接口,允许应用程序通过套接字进行通信。无论是局域网(如AF_UNIX)还是互联网(如AF_INET),socket都通过统一的API进行操作,确保了跨平台的兼容性。
socket操作基于“打开、读写、关闭”的文件式模型。以下是socket的基本函数:
socket(domain, type, protocol)创建一个socket描述符。domain指定协议族(如AF_INET、AF_INET6),type指定socket类型(如STREAM、DATAGRAM),protocol指定协议(如TCP、UDP)。
bind(socket, address, address_len)将socket绑定到指定的地址。address结构体包含IP地址和端口号,address_len指定地址长度。
listen(socket, backlog)将socket设置为被动监听模式,等待客户端连接。connect(socket, address, address_len)建立与远程主机的连接。
accept(socket, address, address_len)接收客户端的连接请求,返回已连接的socket描述符和客户端地址。
read()/write()函数进行网络IO操作,recv()/send()函数同样适用于数据传输。
close(socket)关闭socket描述符,释放相关资源。
TCP连接的建立通过三次握手完成:
在socket编程中,connect()函数负责发送SYN包,accept()函数接收SYN-ACK包并返回已连接socket描述符。
TCP连接的释放通过四次握手完成:
在socket编程中,close()函数负责发送FIN包,连接关闭后,两端的socket描述符需要被关闭。
以下是一个简单的TCP服务器和客户端代码示例:
#include#include #include #include #include using namespace std;#pragma comment(lib, "WS2_32")class CInitSock {public: CInitSock(BYTE minorVer = 2, BYTE majorVer = 2) { WSADATA wsaData; WORD sockVersion = MakeWord(minorVer, majorVer); if (WSAStartup(sockVersion, &wsaData) != 0) { exit(0); } } ~CInitSock() { WSACleanup(); }};int main() { CInitSock initSock; SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sListen == INVALID_SOCKET) { printf("Failed socket()\n"); return 0; } sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(4567); sin.sin_addr.S_un.S_addr = INADDR_ANY; if (bind(sListen, (socklen_t*)&sin, sizeof(sin)) == SOCKET_ERROR) { printf("Failed bind()\n"); return 0; } if (listen(sListen, 2) == SOCKET_ERROR) { printf("Failed listen()\n"); return 0; } sockaddr_in remoteAddr; socklen_t nAddrLen = sizeof(remoteAddr); SOCKET sClient = 0; while (sClient == 0) { sClient = accept(sListen, (socklen_t*)&remoteAddr, (socklen_t*)&nAddrLen); if (sClient == INVALID_SOCKET) { printf("Failed accept()\n"); return 0; } } printf("Accepted connection: %s\n", inet_ntop(remoteAddr.sin_addr.S_un.S_addr)); char szText[] = "TCP Server Demo!\r\n"; while (TRUE) { gets(szText); send(sClient, szText, strlen(szText), 0); char buff[256]; int nRecv = recv(sClient, buff, 256, 0); if (nRecv > 0) { buff[nRecv] = '\0'; printf("Received data: %s\n", buff); } closesocket(sClient); break; } closesocket(sListen); return 0;}
#include#include #include #include #include using namespace std;#pragma comment(lib, "WS2_32")int main() { CInitSock initSock; SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) { printf("Failed socket()\n"); return 0; } sockaddr_in servAddr; servAddr.sin_family = AF_INET; servAddr.sin_port = htons(4567); servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); if (connect(s, (socklen_t*)&servAddr, sizeof(servAddr)) == -1) { printf("Failed connect()\n"); return 0; } char buff[256]; char szText[256]; while (TRUE) { gets(szText); szText[255] = '\0'; send(s, szText, strlen(szText), 0); int nRecv = recv(s, buff, 256, 0); if (nRecv > 0) { buff[nRecv] = '\0'; printf("Received data: %s\n", buff); } closesocket(s); break; } return 0;}
通过以上内容,可以清晰地理解socket在网络通信中的核心作用,以及如何通过socket实现进程间的通信。
转载地址:http://akhg.baihongyu.com/