linux select()详解( 三)-- TCP最简实例

来源:互联网 发布:智能电视网络设置 编辑:程序博客网 时间:2024/05/02 00:12

通过本文你会了解到:
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则下一次将会返回失败。

0 0
原创粉丝点击