当浏览器打开一个网页,或者一款应用连接到服务器时,背后往往有个TCP连接在起作用。TCP(传输控制协议)是一种可靠的、面向连接的协议。在编程中,经常用Socket来建立这样的连接。理解Socket如何建立TCP连接,是搞定网络编程的基础。
步骤1:初始化Socket
第一步是创建一个Socket实例,它会用于监听和接受来自客户端的连接请求:
int sockfd = socket(domain, type, protocol);
这里的domain指定地址族,通常是AF_INET表示IPv4网络协议;type指定类型,SOCK_STREAM是面向连接的套接字,适用于TCP;protocol通常设置为0,让系统自动选择type对应的默认协议,对于TCP来说将会是IPPROTO_TCP。
步骤2:绑定地址和端口
创建好Socket后,需要将它绑定到本机的地址和指定端口上。服务端通过这个端口接收客户端的连接请求。
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port); // 指定端口
addr.sin_addr.s_addr = htonl(INADDR_ANY);
// 监听任何地址
bind(sockfd, (struct sockaddr *)&addr,sizeof(addr));
使用htons和htonl函数处理端口和地址的字节序,确保符合网络协议标准。
步骤3:监听连接
随后,通过调用listen函数使Socket转入监听状态,等待来自客户端的连接请求:
listen(sockfd, backlog);
backlog参数指定了队列中等待的连接数的最大值。
步骤4:接受连接
现在服务端就绪,可以接受客户端的连接请求了:
int client_fd = accept(sockfd, (structsockaddr*)&client_addr, &addr_size);
accept函数会阻塞程序运行,直到一个客户端连接请求到来。这个调用将返回一个新的套接字文件描述符client_fd,之后就可以通过这个新的描述符与刚连接的客户端通信。
客户端如何发起连接
客户端则需要使用connect函数来发起到服务端的连接请求:
connect(socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
这里的server_addr是服务端的地址和端口信息。客户端提供自己的Socket描述符和服务端的地址信息,建立连接。
数据通信
一旦连接建立,服务端和客户端就可以通过读写操作(如read/write或send/recv)来发送和接收数据了。
连接结束
当数据发送接收完毕,最后一步很重要:关闭连接。
服务端和客户端都应调用close函数来关闭各自的Socket:
close(sockfd);
每次结束通信都需要关闭相应Socket,这是良好的网络编程习惯。