linux下socket服务端简单例,多线程,超时退出,长时间没数据就退出,让客户端有需要再重新发起连接

linux下socket服务端简单例,多线程,超时退出


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

//gcc server.c -o server  -lpthread

static const int g_clientTimeout_sec = 60;
static const int g_inValidfd = -1;
static int g_clientSocketfd[200];
static pthread_mutex_t g_client_mutex;

static void sig_exit(int sig)
{
    fprintf(stderr, "sig_exit:%d\n",sig);
    exit(0);
}

static void removeClient(int fd)
{
    int i=0;
    int count  = sizeof (g_clientSocketfd) / sizeof (g_clientSocketfd[0]);
    pthread_mutex_lock(&g_client_mutex);
    for(;i<count;i++){
        if(fd == g_clientSocketfd[i]){
            g_clientSocketfd[i] = g_inValidfd;
            break;
        }
    }
    pthread_mutex_unlock(&g_client_mutex);
}

static void* client_thread(void* arg)
{
    int iRet = 0;
    int curr_flags = 0;
    int clnt_sock = *((int*)arg);
    char buf[100]={0};
    fd_set fdset;
    struct timeval timeout;

    curr_flags = fcntl(clnt_sock, F_GETFL);
    if (curr_flags < 0) {
        perror("fcntl-F_GETFL");
    }
    else if (fcntl(clnt_sock, F_SETFL, curr_flags|O_NONBLOCK) != 0) {
        perror("fcntl-F_SETFL O_NONBLOCK");
    }

    while(1){
        FD_ZERO(&fdset);
        FD_SET(clnt_sock, &fdset);
        timeout.tv_sec = g_clientTimeout_sec;//长时间没数据就退出,让客户端有需要再重新发起连接
        timeout.tv_usec = 0;
        iRet = select(clnt_sock + 1, &fdset, NULL, NULL, &timeout);
        if ((iRet > 0) && (FD_ISSET(clnt_sock, &fdset))) {

            //read all
            while(1){
                memset(buf,0,sizeof (buf));
                iRet = read(clnt_sock,buf,sizeof (buf));
                printf("[%d][%s]\n",iRet,buf);
                if(iRet < 0 && errno == EINTR){
                    continue;
                }
                if(iRet < 1){
                    break;
                }
                //todo 解析包
            }

        } else {
            printf("read timeout.\n");
            break;
        }
    }
    removeClient(clnt_sock);
    close(clnt_sock);
    pthread_detach(pthread_self());

    return  NULL;
}

static int addClient(int fd)
{
    int i=0,iRet = -1;
    int count  = sizeof (g_clientSocketfd) / sizeof (g_clientSocketfd[0]);
    pthread_t th;
    pthread_mutex_lock(&g_client_mutex);
    for(;i<count;i++){
        if(g_inValidfd  == g_clientSocketfd[i]){
            g_clientSocketfd[i] = fd;
            if (pthread_create(&th, NULL, client_thread, (void*)(g_clientSocketfd+i)) != 0){
                perror("创建处理线程失败:");
                g_clientSocketfd[i] = g_inValidfd;
            }else{
                iRet = 0;
            }
            break;
        }
    }
    pthread_mutex_unlock(&g_client_mutex);
    return  iRet;
}

int main()
{
    int reuseaddr = 1;
    int retval = 0;
    int serv_sock = -1;
    int clnt_sock = -1;
    int max_client_count = 0;
    socklen_t clnt_addr_size;
    struct sockaddr_in serv_addr;
    struct sockaddr_in clnt_addr;

    (void) signal(SIGUSR1, sig_exit);
    (void) signal(SIGCHLD, SIG_IGN);
    (void) signal(SIGTSTP, sig_exit);
    (void) signal(SIGINT, SIG_IGN);
    (void) signal(SIGPIPE, SIG_IGN);
    (void) signal(SIGKILL, sig_exit);
    (void) signal(SIGSEGV, sig_exit);

    pthread_mutex_init(&g_client_mutex, NULL);
    max_client_count = sizeof (g_clientSocketfd) / sizeof (g_clientSocketfd[0]);
    for(retval=0;retval<max_client_count;retval++){
        g_clientSocketfd[retval] = g_inValidfd;
    }

    serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(serv_sock < 1){
        perror("socket");
        return -1;
    }
    retval = setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,sizeof(reuseaddr));
    if (retval != 0) {
        perror("setsockopt: reuseaddr");
    }
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//inet_addr("127.0.0.1");
    serv_addr.sin_port = htons(6666);
    retval = bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    if (retval != 0) {
        perror("bind");
        return -1;
    }

    retval = listen(serv_sock, 20);
    if (retval != 0) {
        perror("listen");
        return -1;
    }

    clnt_addr_size = sizeof(clnt_addr);
    while(1)
    {
        clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
        if(-1 == addClient(clnt_sock)){
            close(clnt_sock);
        }
    }
    close(serv_sock);
    pthread_mutex_destroy(&g_client_mutex);
    return 0;
}



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值