c语言实现简单的tcp服务端

功能:监听本地8888端口,接收到客户端连接请求后创建线程单独处理与客户端的交互,支持同时与多个客户端交互。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

#define PORT 8888

void *deal_client(void *args)
{
    int fd;
    int i;
    unsigned char recv_buff[1024] = {0};
    int read_len = 0;
    int send_len = 0;
    unsigned char *send_data = "hello,this is a tcp server\n";

    fd = (int) *(int *) args;
    printf("fd %d\n", fd);
    if (fd < 0)
    {
        printf("socket err\n");
        return NULL;
    }

    while (1)
    {
        memset(recv_buff, 0x00, sizeof (recv_buff));

        read_len = recv(fd, recv_buff, sizeof (recv_buff), 0);
        if (read_len < 0)
        {
            printf("recv err\n");
            close(fd);
            fd = -1;
            return NULL;
        } else if (read_len == 0)
        {
            printf("close \n");
            close(fd);
            fd = -1;
            return NULL;
        }


        printf("recv data: %s\n", recv_buff);
        //        for (i = 0; i < read_len; i++)
        //        {
        //            printf("%02x ", recv_buff[i]);
        //        }
        //        printf("\n");

        send_len = send(fd, send_data, strlen(send_data), 0);
        if (send_len <= 0)
        {
            printf("send err\n");
            close(fd);
            fd = -1;
            return NULL;
        }
    }
}

int main()
{
    //创建套接字
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd < 0)
    {
        printf("socket err\n");
        return -1;
    }
    printf("socket create success sfd=%d\n", socket_fd);

    //设置端口重用
    int resue = 1;
    if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &resue, sizeof (resue)) < 0)
    {
        printf("setsockopt SO_REUSEADDR err\n");
        return -1;
    }

    //填充服务器的地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(PORT);
    sin.sin_addr.s_addr = inet_addr("0.0.0.0");

    //绑定端口号
    if (bind(socket_fd, (struct sockaddr*) &sin, sizeof (sin)) < 0)
    {
        printf("bind err\n");
        return -1;
    }
    printf("bind success\n");

    //监听端口号
    if (listen(socket_fd, 5) == -1)
    {
        printf("listen err\n");
        return -1;
    }
    printf("listen success\n");

    while (1)
    {
        struct sockaddr_in cin; //存储连接成功的客户端地址
        socklen_t addrlen = sizeof (cin);
        int socket_cli = -1;

        socket_cli = accept(socket_fd, (struct sockaddr*) &cin, &addrlen);
        if (socket_cli < 0)
        {
            printf("accept err\n");
            continue;
        }
        printf("socket_cli %d\n", socket_cli);
        pthread_t tid = -1;
        pthread_create(&tid, NULL, deal_client, &socket_cli);

        usleep(1000); //注意这里必须sleep一下,不然参数传递不过去
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TCP是一种可靠的传输协议,因此在实现TCP服务端重连时,需要考虑如下几个方面: 1. 断开连接的检测 服务端需要定期检测与客户的连接是否已经断开,可以通过定时发送心跳包的方式来实现。如果服务端检测到连接已经断开,可以将之前的套接字关闭,并重新创建一个套接字来监听客户的连接请求。 2. 重连的处理 当服务端检测到与客户的连接已经断开后,需要重新创建一个套接字来监听客户的连接请求。在客户重新连接后,服务端需要重新与客户建立连接,并进行数据的交互。 下面是一个简单C语言实现TCP服务端重连的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 8888 #define MAXLINE 1024 int main(int argc, char **argv) { int listenfd, connfd; struct sockaddr_in servaddr, cliaddr; socklen_t clilen; char buf[MAXLINE]; int n; // 创建套接字 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket error"); exit(1); } // 设置地址结构体 memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PORT); // 绑定套接字 if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) { perror("bind error"); exit(1); } // 监听套接字 if (listen(listenfd, 10) == -1) { perror("listen error"); exit(1); } while (1) { // 接受客户连接 clilen = sizeof(cliaddr); if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen)) == -1) { perror("accept error"); continue; } // 连接成功 printf("connection established\n"); while (1) { // 接收数据 n = read(connfd, buf, MAXLINE); if (n == -1) { perror("read error"); break; } else if (n == 0) { printf("client closed\n"); break; } // 打印数据 buf[n] = '\0'; printf("recv: %s", buf); // 发送数据 if (write(connfd, buf, n) == -1) { perror("write error"); break; } } // 关闭套接字 close(connfd); } return 0; } ``` 在上面的示例代码中,我们使用了一个无限循环来接受客户的连接,并在连接成功后进入另一个无限循环来接收客户发送的数据。如果客户断开连接,服务端会关闭套接字,并等待下一个客户连接。如果服务端检测到连接已经断开,会关闭之前的套接字,并重新创建一个套接字来监听客户的连接请求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值