linux select()详解( 三)-- TCP最简实例
2016-06-04 18:21
423 查看
通过本文你会了解到:
1. TCP server的实例
2. TCP client的实例
3. TCP server和client的运行测试
4. TCP C/S模型的思考
约定
1. 格式为 /**/ 的注释对程序的主要流程进行说明
2. 格式为 // 的注释对程序的难懂语句进行说明
TCP server实例(server.c)
TCP client实例(client.c)
TCP server和client的运行测试
TCP C/S模型的思考
在TCP连接关闭时,连接会进入TIME_WAIT状态,经过2个MSL时间后关闭,因此如果client频繁连接和关闭,如果在2个MSL时间内令连接数达到1024则下一次将会返回失败。
1. TCP server的实例
2. TCP client的实例
3. TCP server和client的运行测试
4. TCP C/S模型的思考
约定
1. 格式为 /**/ 的注释对程序的主要流程进行说明
2. 格式为 // 的注释对程序的难懂语句进行说明
TCP server实例(server.c)
#include <stdio.h> /* for printf() and fprintf() */ #include <sys/types.h> /* for Socket data types */ #include <sys/socket.h> /* for socket(), connect(), send(), and recv() */ #include <netinet/in.h> /* for IP Socket data types */ #include <arpa/inet.h> /* for sockaddr_in and inet_addr() */ #include <stdlib.h> /* for exit() */ #include <string.h> /* for memset() */ #include <unistd.h> /* for close() */ #include <errno.h> /* for errno*/ //macro #define BUF_SIZE 1024 #define PORT 1025 #undef max #define max(x, y) ((x) > (y) ? (x) : (y)) #undef handle_error #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while(0) int main(int argc, char *argv[]) { struct sockaddr_in server_addr; struct sockaddr_in conn_addr; fd_set read_fds; socklen_t len; char buf[BUF_SIZE]; int conn_fd = -1; int server_fd = -1; int ret; /*创建tcp描述符*/ server_fd = socket(AF_INET, SOCK_STREAM, 0); if(server_fd == -1) handle_error("socket"); /*指定server信息并绑定*/ memset(&server_addr, 0, sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //ip地址为任意,只要port满足即可 if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) handle_error("bind"); /*监听server描述符*/ if(listen(server_fd, 5) == -1) handle_error("listen"); printf("accepting connections on port %d\n", PORT); while(1) { int max_fd = 0; FD_ZERO(&read_fds); FD_SET(server_fd ,&read_fds); max_fd = max(server_fd, max_fd); if(conn_fd > 0) { FD_SET(conn_fd ,&read_fds); max_fd = max(conn_fd, max_fd); } /*检测描述符集中的描述符的I/O状态*/ ret = select(max_fd + 1, &read_fds, NULL, NULL, NULL); if(ret == -1 && errno == EINTR) continue; if(ret == -1) handle_error("select"); if(FD_ISSET(server_fd, &read_fds)) { //server_fd可读,即有client连接 len = sizeof(conn_addr); if(conn_fd > 0) { //如果已有连接,则先关闭,因此此server只与最后一次连接的client进行通信 close(conn_fd); } /*接受并得到client信息*/ conn_fd = accept(server_fd, (struct sockaddr *)&conn_addr, &len); if(conn_fd == -1) handle_error("accept"); printf("client is connected\n"); } else if(FD_ISSET(conn_fd, &read_fds)) { //conn_fd可读,即接收到client数据 int n; memset(buf, 0, BUF_SIZE); n = recv(conn_fd, buf, BUF_SIZE, 0); if(n == -1) { //recv函数返回错误 perror("recv"); close(conn_fd); conn_fd = -1; } else if(n == 0) { //client端套接字被关闭 printf("client is closed\n"); close(conn_fd); conn_fd = -1; } else { //读取成功 /*对收到的数据进行处理*/ printf("receive data:%s\n", buf); } } } /*关闭描述符*/ close(server_fd); return 0; }
TCP client实例(client.c)
#include <stdio.h> /* for printf() */ #include <sys/types.h> /* for Socket data types */ #include <sys/socket.h> /* for socket(), connect(), send(), and recv() */ #include <netinet/in.h> /* for IP Socket data types */ #include <arpa/inet.h> /* for sockaddr_in and inet_addr() */ #include <stdlib.h> /* for exit() */ #include <string.h> /* for memset() */ #include <unistd.h> /* for close() */ #include <errno.h> /* for errno*/ //macro #define BUF_SIZE 1024 #define PORT 1025 #define SEND_PACK_CNT 3 #define SRV_IP "127.0.0.1" #undef handle_error #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while(0) int main(int argc, char *argv[]) { struct sockaddr_in server_addr; char buf[BUF_SIZE]; int conn_fd = -1; int i; /*创建tcp描述符*/ conn_fd = socket(AF_INET, SOCK_STREAM, 0); if(conn_fd == -1) handle_error("socket"); /*指定将连接的server信息*/ memset(&server_addr, 0, sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); if (inet_aton(SRV_IP, &server_addr.sin_addr) == 0) handle_error("inet_aton"); /*连接到server*/ if(connect(conn_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) handle_error("connect"); printf("connect to server ip:%s port:%d\n", SRV_IP, PORT); for(i = 0; i < SEND_PACK_CNT; i++) { sprintf(buf, "Packet %d", i); printf("send to server: %s\n", buf); /*发送数据*/ send(conn_fd, buf, strlen(buf) + 1, 0); sleep(2); } /*关闭描述符*/ printf("close\n"); close(conn_fd); return 0; }
TCP server和client的运行测试
TCP C/S模型的思考
在TCP连接关闭时,连接会进入TIME_WAIT状态,经过2个MSL时间后关闭,因此如果client频繁连接和关闭,如果在2个MSL时间内令连接数达到1024则下一次将会返回失败。
相关文章推荐
- In Gradle projects, always use http://schemas.android.com/apk/res-auto for custom attributes
- WebApi接口安全认证——HTTP之摘要认证
- 使用 acl 编写 UDP 网络程序(UDP 重传及可靠性机制)
- 基于HTTP 协议认证介绍与实现
- HttpURLConnection getResponseCode()方法阻塞
- 配置nginx负载TCP服务器
- HTTP 请求方式: GET和POST的比较
- JavaScript---网络编程(3)-Object、String、Array对象和prototype属性
- JavaScript---网络编程(3)-Object、String、Array对象和prototype属性
- 解决- schema_reference.4: Failed to read schema document 'http://www.springframe
- Edusoho 网络课堂安装教程
- 基于Linux的网络编程
- 网络编程的基本概念
- Android Http缓存数据处理
- 开源的49款Java 网络爬虫软件
- HTTP的请求方法OPTIONS
- 《Indy In Depth》中文版
- 安卓HTTP实例中post方法和get方法的区别
- ISCSI 用法及简单配置
- TCP滑动窗口机制