跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C 语言网络编程基础
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C语言网络编程基础 = '''C语言网络编程'''是指使用C语言及相关库函数实现计算机之间的网络通信。它是系统编程和网络技术的结合,广泛应用于服务器开发、嵌入式设备通信、网络安全工具等领域。本节将介绍基础概念、核心API及实际应用案例。 == 核心概念 == 网络编程的核心是'''套接字'''(Socket),它是网络通信的端点,允许不同主机或同一主机的不同进程间交换数据。主要分为两类: * '''流式套接字'''(SOCK_STREAM):基于TCP协议,提供可靠、面向连接的通信 * '''数据报套接字'''(SOCK_DGRAM):基于UDP协议,提供无连接的快速通信 <mermaid> graph LR A[应用程序] -->|调用| B[socket()] B --> C[bind()] C --> D[listen()/connect()] D --> E[accept()/send()/recv()] </mermaid> == 基础API详解 == === 创建套接字 === 使用<code>socket()</code>函数创建通信端点: <syntaxhighlight lang="c"> #include <sys/socket.h> int socket(int domain, int type, int protocol); </syntaxhighlight> 示例创建TCP套接字: <syntaxhighlight lang="c"> int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket creation failed"); exit(EXIT_FAILURE); } </syntaxhighlight> === 地址结构 === 网络地址使用<code>sockaddr_in</code>结构体: <syntaxhighlight lang="c"> struct sockaddr_in { sa_family_t sin_family; // 地址族,如AF_INET in_port_t sin_port; // 端口号(网络字节序) struct in_addr sin_addr; // IP地址 }; struct in_addr { uint32_t s_addr; // 32位IP地址 }; </syntaxhighlight> === 服务器端流程 === 1. 绑定地址:<code>bind()</code> 2. 监听连接:<code>listen()</code> 3. 接受连接:<code>accept()</code> 示例服务器代码: <syntaxhighlight lang="c"> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define PORT 8080 #define BACKLOG 5 int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); // 创建套接字 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置套接字选项 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // 绑定 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听 if (listen(server_fd, BACKLOG) < 0) { perror("listen"); exit(EXIT_FAILURE); } printf("Server listening on port %d\n", PORT); // 接受连接 if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } char buffer[1024] = {0}; read(new_socket, buffer, 1024); printf("Message from client: %s\n", buffer); char *hello = "Hello from server"; send(new_socket, hello, strlen(hello), 0); close(new_socket); close(server_fd); return 0; } </syntaxhighlight> === 客户端流程 === 1. 连接服务器:<code>connect()</code> 2. 发送/接收数据:<code>send()</code>/<code>recv()</code> 示例客户端代码: <syntaxhighlight lang="c"> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define PORT 8080 int main() { int sock = 0; struct sockaddr_in serv_addr; char *hello = "Hello from client"; char buffer[1024] = {0}; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("\n Socket creation error \n"); return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); // 转换IP地址 if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { printf("\nInvalid address/ Address not supported \n"); return -1; } if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf("\nConnection Failed \n"); return -1; } send(sock, hello, strlen(hello), 0); printf("Hello message sent\n"); read(sock, buffer, 1024); printf("Server: %s\n", buffer); close(sock); return 0; } </syntaxhighlight> == 字节序转换 == 网络字节序(大端序)与主机字节序转换函数: * <code>htons()</code> - 主机到网络(短整型) * <code>htonl()</code> - 主机到网络(长整型) * <code>ntohs()</code> - 网络到主机(短整型) * <code>ntohl()</code> - 网络到主机(长整型) == 实际应用案例 == === 简易聊天程序 === 结合多线程实现双向通信: <syntaxhighlight lang="c"> // 服务器端接收线程 void *receive_handler(void *socket_desc) { int sock = *(int*)socket_desc; char buffer[1024]; while (1) { int read_size = recv(sock, buffer, sizeof(buffer), 0); if (read_size > 0) { buffer[read_size] = '\0'; printf("Client: %s", buffer); } } return NULL; } // 主函数中创建线程 pthread_t recv_thread; if (pthread_create(&recv_thread, NULL, receive_handler, (void*)&new_socket) < 0) { perror("could not create thread"); return 1; } </syntaxhighlight> === 文件传输协议 === 实现基础文件传输功能: <syntaxhighlight lang="c"> // 发送文件函数 void send_file(FILE *fp, int sockfd) { char data[1024] = {0}; while (fgets(data, sizeof(data), fp) != NULL) { if (send(sockfd, data, sizeof(data), 0) == -1) { perror("Error in sending file"); exit(1); } bzero(data, sizeof(data)); } } </syntaxhighlight> == 常见问题与调试 == {| class="wikitable" |- ! 错误现象 !! 可能原因 !! 解决方案 |- | <code>Address already in use</code> || 端口被占用 || 使用<code>setsockopt()</code>设置<code>SO_REUSEADDR</code> |- | <code>Connection refused</code> || 服务器未运行/防火墙阻止 || 检查服务器状态和防火墙设置 |- | 数据截断 || 缓冲区大小不足 || 增加缓冲区或分块传输 |} == 进阶主题 == * 多路复用(select/poll/epoll) * 非阻塞I/O * SSL/TLS加密通信 * IPv6编程(<code>AF_INET6</code>) 通过掌握这些基础知识,您已经具备了开发简单网络应用的能力。实际项目中还需考虑错误处理、性能优化和安全性等问题。 [[Category:编程语言]] [[Category:C]] [[Category:C 语言网络编程]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)