C/C++ Linux Socket网络编程流程分析
什么是Socket
Socket是计算机网络中对于通信队列和编程接口的抽象。一句话概括,Socket是一种特殊的文件,它通过文件IO的方式向网络发送和接收数据。
Socket网络编程流程
- 创建Socket
创建一个Socket需要调用socket()函数,它有三个参数,分别是:地址族、类型、协议。在Linux中,地址族常用的有AF_INET(IPv4)和AF_INET6(IPv6)两种,类型常用的有SOCK_STREAM和SOCK_DGRAM两种,协议有TCP和UDP两种。
示例代码:
// 创建一个IPv4地址族、使用TCP协议的Socket
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- 绑定Socket
在Socket创建之后,需要将这个Socket绑定到一个具体的端口上,在Linux中,端口号是一个16位的非负整数。
示例代码:
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// 将Socket绑定到8080端口
int ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret == -1) {
perror("bind error");
exit(EXIT_FAILURE);
}
- 监听Socket
当Socket绑定到端口上之后,需要将这个Socket转换成监听状态,等待客户端的连接。
示例代码:
// 开始监听客户端请求
int backlog = 10;
ret = listen(sockfd, backlog);
if (ret == -1) {
perror("listen error");
exit(EXIT_FAILURE);
}
- 接受连接
当有客户端连接请求到达服务器时,需要调用accept()函数接受连接请求,并创建新的Socket与客户端通信。
示例代码:
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
// 等待客户端的连接请求
int newsockfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len);
if (newsockfd == -1) {
perror("accept error");
exit(EXIT_FAILURE);
}
- 读写Socket
在建立连接之后,客户端和服务器之间就可以通过Socket互相发送数据了。可以使用read()和write()函数进行数据读写。
示例代码:
// 从客户端读取数据
char buf[1024];
int n = read(newsockfd, buf, sizeof(buf));
if (n == -1) {
perror("read error");
exit(EXIT_FAILURE);
}
// 向客户端发送数据
const char* msg = "Hello, client!";
n = write(newsockfd, msg, strlen(msg));
if (n == -1) {
perror("write error");
exit(EXIT_FAILURE);
}
- 关闭Socket
在通信结束后,需要关闭Socket来释放资源。
示例代码:
// 关闭Socket
close(newsockfd);
close(sockfd);
示例:TCP服务器
下面是一个简单的TCP服务器示例代码,它可以监听8080端口,并将客户端发送来的字符串原样回发到客户端。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
// 创建Socket
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd == -1) {
perror("socket error");
exit(EXIT_FAILURE);
}
// 绑定到8080端口
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret == -1) {
perror("bind error");
exit(EXIT_FAILURE);
}
// 开始监听客户端请求
int backlog = 10;
ret = listen(sockfd, backlog);
if (ret == -1) {
perror("listen error");
exit(EXIT_FAILURE);
}
// 循环等待客户端连接
while (true) {
// 等待客户端连接请求
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int newsockfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len);
if (newsockfd == -1) {
perror("accept error");
exit(EXIT_FAILURE);
}
// 从客户端读取字符串
char buf[1024];
int n = read(newsockfd, buf, sizeof(buf));
if (n == -1) {
perror("read error");
exit(EXIT_FAILURE);
}
buf[n] = '\0';
printf("Received message from client: %s\n", buf);
// 回发字符串到客户端
n = write(newsockfd, buf, n);
if (n == -1) {
perror("write error");
exit(EXIT_FAILURE);
}
// 关闭连接
close(newsockfd);
}
// 关闭Socket
close(sockfd);
return 0;
}
示例:TCP客户端
下面是一个简单的TCP客户端示例代码,它可以连接到127.0.0.1的8080端口,并向服务器发送一个字符串,并等待服务器回发字符串。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
// 创建Socket
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd == -1) {
perror("socket error");
exit(EXIT_FAILURE);
}
// 连接到服务器
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
inet_aton("127.0.0.1", &server_addr.sin_addr);
int ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret == -1) {
perror("connect error");
exit(EXIT_FAILURE);
}
// 向服务器发送字符串
const char* msg = "Hello, server!";
int n = write(sockfd, msg, strlen(msg));
if (n == -1) {
perror("write error");
exit(EXIT_FAILURE);
}
// 等待服务器回发字符串
char buf[1024];
n = read(sockfd, buf, sizeof(buf));
if (n == -1) {
perror("read error");
exit(EXIT_FAILURE);
}
buf[n] = '\0';
printf("Received message from server: %s\n", buf);
// 关闭Socket
close(sockfd);
return 0;
}
以上就是C/C++ Linux Socket网络编程的简单流程以及两个示例代码的讲解。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C/C++ Linux Socket网络编程流程分析 - Python技术站