博客
关于我
Socket通信原理和基础实践
阅读量:366 次
发布时间:2019-03-05

本文共 4330 字,大约阅读时间需要 14 分钟。

网络进程间通信是计算机科学中的一个基础问题,socket作为实现网络通信的核心工具,在现代网络应用中无处不在。本文将从网络通信的基本原理出发,深入探讨socket的工作机制及其在TCP协议中的应用。

1. 网络进程间通信

在网络环境中,进程间通信需要唯一标识每个进程。TCP/IP协议族通过三元组(IP地址、协议、端口)实现这一点:IP地址唯一标识网络中的主机,而协议和端口则唯一标识主机中的应用程序。这种标识机制使得网络中的进程通信变得可能。

在Unix系统中,socket提供了一种统一的接口,允许应用程序通过套接字进行通信。无论是局域网(如AF_UNIX)还是互联网(如AF_INET),socket都通过统一的API进行操作,确保了跨平台的兼容性。

2. socket的基本操作

socket操作基于“打开、读写、关闭”的文件式模型。以下是socket的基本函数:

2.1 socket()函数

socket(domain, type, protocol)创建一个socket描述符。domain指定协议族(如AF_INET、AF_INET6),type指定socket类型(如STREAM、DATAGRAM),protocol指定协议(如TCP、UDP)。

2.2 bind()函数

bind(socket, address, address_len)将socket绑定到指定的地址。address结构体包含IP地址和端口号,address_len指定地址长度。

2.3 listen()、connect()函数

listen(socket, backlog)将socket设置为被动监听模式,等待客户端连接。connect(socket, address, address_len)建立与远程主机的连接。

2.4 accept()函数

accept(socket, address, address_len)接收客户端的连接请求,返回已连接的socket描述符和客户端地址。

2.5 read()、write()等函数

read()/write()函数进行网络IO操作,recv()/send()函数同样适用于数据传输。

2.6 close()函数

close(socket)关闭socket描述符,释放相关资源。

3. TCP三次握手建立连接

TCP连接的建立通过三次握手完成:

  • 客户端发送SYN包。
  • 服务器响应SYN-ACK包。
  • 客户端发送ACK包。
  • 在socket编程中,connect()函数负责发送SYN包,accept()函数接收SYN-ACK包并返回已连接socket描述符。

    4. TCP四次握手释放连接

    TCP连接的释放通过四次握手完成:

  • 应用进程调用close(),发送FIN包。
  • 对方接收FIN包并确认。
  • 对方发送FIN包。
  • 应用进程确认。
  • 在socket编程中,close()函数负责发送FIN包,连接关闭后,两端的socket描述符需要被关闭。

    5. 实际应用示例

    以下是一个简单的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;}

    6. 重要注意事项

    • socket编程涉及到网络字节序转换,确保正确处理主机字节序和网络字节序。
    • TCP连接是可靠的,但UDP是无连接的,需要额外处理。
    • 在网络应用中,应妥善处理错误和异常情况,如EINTR、ECONNRESET等。

    通过以上内容,可以清晰地理解socket在网络通信中的核心作用,以及如何通过socket实现进程间的通信。

    转载地址:http://akhg.baihongyu.com/

    你可能感兴趣的文章
    图像处理系列1.skimage
    查看>>
    好用的拼图小程序,图作妖
    查看>>
    读取二进制存储信息,将低位二进制存储转换为高位存储
    查看>>
    Hibernate操作Blob,将Blob转换为String
    查看>>
    Object Clone
    查看>>
    Javascript中String支持使用正则表达式的四种方法
    查看>>
    2021年判断浏览器最新写法,你都掌握了吗?
    查看>>
    简易版Http请求工具
    查看>>
    【法律】如何保障企业的合法权益:保密协议模板
    查看>>
    【IoT】 产品设计之结构设计:材料工艺选择及特点(PP、PVC、PE、PS、ABS、PC)
    查看>>
    【IoT】 产品设计之结构设计:PMMA(亚克力)板、PC耐力板、PS有机板与MS板区别
    查看>>
    【IoT】蓝牙BLE基础:CC254x通信系列之模拟SPI协议
    查看>>
    【IoT】TI BLE CC2541 串口控制蓝牙详解
    查看>>
    【企业】走近华为,微观世界
    查看>>
    【产品】项目管理的五个过程和九大知识领域之二
    查看>>
    【项目管理】项目管理流程浅析
    查看>>
    【企业】韬盛和夫六精进
    查看>>
    【Tool】如何使用 Uniflash 烧写 WIFI 芯片 CC3200
    查看>>
    html2canvas vue页面截图生成图片地址
    查看>>
    copy_{to, from}_user()的思考
    查看>>