
本文将深入探讨使用套接字进行网络通信的基本步骤,包括创建套接字、绑定地址、监听连接(对于服务器端)、连接远程主机(对于客户端)、以及发送和接收数据等操作。套接字编程涉及一系列系统调用和函数,如 socket()、bind()、listen()、connect()、send()、recv() 等。开发人员可以利用这些接口实现各种网络应用。通过本文,读者将了解如何使用套接字进行网络通信,并掌握关键步骤和函数调用,为构建网络应用打下坚实基础。
| 函数 | 描述 |
|---|---|
| socket() | 创建一个新的套接字 |
| bind() | 将套接字绑定到特定的IP地址和端口号上 |
| listen() | 将套接字标记为被动套接字,用于监听连接请求 |
| accept() | 接受客户端的连接请求,并返回一个新的套接字用于通信 |
| connect() | 建立与服务器端的连接 |
| send() | 发送数据 |
| recv() | 接收数据 |
| sendto() | 用于UDP协议中发送数据 |
| recvfrom() | 用于UDP协议中接收数据 |
| close() | 关闭套接字连接 |
| select() | 多路复用,同时监视多个套接字的状态 |
| getaddrinfo() | 主机名和服务名之间的转换 |
| setsockopt() | 设置套接字选项 |
| getsockopt() | 获取套接字选项的值 |
| inet_pton() | IP地址的转换 |
| inet_ntop() | IP地址的转换 |
| htons() | 主机字节序和网络字节序之间的转换(16位整数) |
| ntohs() | 主机字节序和网络字节序之间的转换(16位整数) |
| htonl() | 主机字节序和网络字节序之间的转换(32位整数) |
| ntohl() | 主机字节序和网络字节序之间的转换(32位整数) |
头文件:#include
函数原型:int socket(int domain, int type, int protocol);
参数类型:
应用示例:
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
头文件:#include
函数原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数类型:
应用示例:
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(12345);
server_address.sin_addr.s_addr = INADDR_ANY;
bind(sockfd, (struct sockaddr *)&server_address, sizeof(server_address));
头文件:#include
函数原型:int listen(int sockfd, int backlog);
参数类型:
应用示例:
listen(sockfd, 5);
头文件:#include
函数原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数类型:
应用示例:
int client_sockfd = accept(sockfd, (struct sockaddr *)&client_address, &addr_len);
头文件:#include
函数原型:int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数类型:
应用示例:
connect(sockfd, (struct sockaddr *)&server_address, sizeof(server_address));
头文件:#include
函数原型:ssize_t send(int sockfd, const void *buf, size_t len, int flags);
参数类型:
应用示例:
char *message = "Hello, server!";
send(sockfd, message, strlen(message), 0);
头文件:#include
函数原型:ssize_t recv(int sockfd, void *buf, size_t len, int flags);
参数类型:
应用示例:
char buffer[1024];
ssize_t bytes_received = recv(sockfd, buffer, 1024, 0);
头文件:#include
函数原型:int close(int sockfd);
参数类型:
应用示例:
close(sockfd);
头文件:#include
函数原型:int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
参数类型:
应用示例:
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
int activity = select(sockfd + 1, &readfds, NULL, NULL, NULL);
头文件:#include
#include
#include
函数原型:int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
参数类型:
应用示例:
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("www.example.com", "http", &hints, &res);
头文件:#include
函数原型:ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
参数类型:
应用示例:
char *message = "Hello, server!";
sendto(sockfd, message, strlen(message), 0, (struct sockaddr *)&server_address, sizeof(server_address));
头文件:#include
函数原型:ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
参数类型:
应用示例:
char buffer[1024];
struct sockaddr_in client_address;
socklen_t addr_len = sizeof(client_address);
ssize_t bytes_received = recvfrom(sockfd, buffer, 1024, 0, (struct sockaddr *)&client_address, &addr_len);
头文件:#include
函数原型:int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
参数类型:
应用示例:
int reuse = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
头文件:#include
函数原型:int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
参数类型:
应用示例:
int buffer_size;
socklen_t optlen = sizeof(buffer_size);
getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &buffer_size, &optlen);
头文件:#include
函数原型:int shutdown(int sockfd, int how);
参数类型:
应用示例:
shutdown(sockfd, SHUT_RDWR);
头文件:#include
函数原型:int inet_pton(int af, const char *src, void *dst);
参数类型:
应用示例:
struct sockaddr_in server_address;
inet_pton(AF_INET, "127.0.0.1", &(server_address.sin_addr));
这些函数用于主机字节序和网络字节序之间的转换,分别用于16位和32位整数的主机到网络字节序以及网络到主机字节序的转换。
头文件:#include
函数原型:
这些函数在实际网络编程中经常用于端口号和IP地址等数据的转换。
感谢您对博主文章的关注与支持!如果您喜欢这篇文章,可以点赞、评论和分享给您的同学,这将对我提供巨大的鼓励和支持。另外,我计划在未来的更新中持续探讨与本文相关的内容。我会为您带来更多关于Linux以及C++编程技术问题的深入解析、应用案例和趣味玩法等。如果感兴趣的话可以关注博主的更新,不要错过任何精彩内容!
再次感谢您的支持和关注。我们期待与您建立更紧密的互动,共同探索Linux、C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!
