linux基础编程 套接字socket 完整的服务器端多线程socket程序【转】

简介:

转自:http://blog.csdn.net/ghostyu/article/details/7737203

复制代码
此段程序来自我的一个项目中,稍微做了些修改,运行稳定,客户端程序比较简单所以未编写,可以用socket调试工具测试此段代码

费话不多说,直接上代码

[cpp] view plain copy

    #include<stdlib.h>   
    #include<stdio.h>   
    #include<string.h>   
    #include<errno.h>   
    #include<netdb.h>   
    #include<sys/types.h>   
    #include<netinet/in.h>   
    #include<sys/socket.h>   
    #include<sys/wait.h>   
    #include<unistd.h>   
    #include<pthread.h>   
    #include<fcntl.h>  
      
    #define __DEBUG  
    #ifdef __DEBUG  
    #define DBG(fmt,args...) fprintf(stdout,  fmt,  ##args)  
    #else  
    #define DBG(fmt,args...)  
    #endif  
    #define ERR(fmt,args...) fprintf(stderr,  fmt,  ##args)  
      
    /* 
    isStreamQuit == 0 :Start 
    isStreamQuit == 1 :Client Quit 
    isStreamQuit ==-1 :App Quit 
    */  
    static int isStreamQuit    = 0;  
    static int gStreamServerFd = -1;  
    int gStreamClientFd;  
      
    #define PORT_SOCKET          9000   //server监听端口  
    #define RECV_BUF_MAX_LEN     512  
    #define TIME_WAIT            200000     /*200ms*/  
      
    /* 
    socket发送函数 
     */  
    int ScketSend(unsigned char *buf,unsigned int len)  
    {  
          
        int ret = 0;  
        if(gStreamClientFd <= 0)  
            return -1;  
        ret = send(gStreamClientFd,buf,len,0);  
        if(ret <= 0 ){  
            return -1;  
        }else if(ret == len){  
            return 0;  
        }  
        while(ret < len){  
            ret += send(gStreamClientFd,buf+ret,len-ret,0);  
        }  
        return 0;  
    }  
      
    /* 
    socket连接线程,阻塞等待客户端的连接, 
    连接后循环处理客户端发来的数据, 
    这里只能连接一个客户端,稍加修改,就可以支持多客户端连接 
    */  
    void *SocketThread(void *arg)  
    {  
        fd_set SockRead;  
        struct timeval TimeOut;  
        int ret;  
        struct sockaddr clientAddr;   
        unsigned char *rcvBuf = (unsigned char *)malloc(RECV_BUF_MAX_LEN);  
          
        socklen_t  len;  
        len = sizeof(clientAddr);  
        while(1){  
              
            int rcvLen;  
            /*阻塞等待客户端连接*/  
            gStreamClientFd = accept(gStreamServerFd, &clientAddr, &len);  
            if(gStreamClientFd == -1){  
                ERR("ERROR in stream accept: %s\n",strerror(errno));  
                /*add errno handler here,in some case,the error is not fatal*/  
                /*code here*/  
                break;  
            }  
            /*isStreamQuit == -1,is the siganl to quit*/  
            if(isStreamQuit != -1){  
                isStreamQuit = 0;  
            }  
            DBG("accep a stream client\n");  
            /*客户端已连接,循环处理*/  
            while(isStreamQuit==0){  
                FD_ZERO(&SockRead);  
                FD_SET(gStreamClientFd,&SockRead);  
                TimeOut.tv_sec = 0;  
                TimeOut.tv_usec = TIME_WAIT;  
                /* 
                200ms超时判断是否有数据接收,有则接收,没有继续循环, 
                总是让程序不能一直阻塞在这里 
                */  
                ret = select(gStreamClientFd+1,&SockRead,NULL,NULL,&TimeOut);  
                if(ret == -1){  
                    ERR("ERROR in select\n");  
                    break;  
                }else if(ret == 0){  
                    continue;  
                }  
                /*接收客户端发来的数据*/  
                rcvLen = recv(gStreamClientFd,rcvBuf,RECV_BUF_MAX_LEN,0);  
                if(rcvLen < 0){  
                    ERR("ERROR in stream accept: %s\n",strerror(errno));  
                    /*add errno handler here,in some case,the error is not fatal*/  
                    /*code here*/  
                    isStreamQuit = 1;  
                    break;  
                }else if(rcvLen == 0){  
                    DBG("stream client close\n");  
                    /*code here*/  
                    isStreamQuit = 1;  
                    break;  
                }  
                DBG("rcvLen: %d,rcvBuf: %s\n",rcvLen,rcvBuf);  
      
                memset(rcvBuf,0,RECV_BUF_MAX_LEN);  
            }  
            DBG("Close Stream Socket\n");  
            close(gStreamClientFd);  
              
            /*OTHER Error or App Quit*/  
            if(isStreamQuit == -1){  
                break;  
            }  
      
        }  
        DBG("SocketThread exit\n");  
        free(rcvBuf);  
        close(gStreamServerFd);  
        pthread_exit(NULL);  
    }  
      
    /* 
    socket连接初始化 
    */  
    int SocketInit()  
    {  
        struct sockaddr_in server;  
        pthread_t tStreamSocketThr;  
        /*创建socket*/  
        gStreamServerFd = socket(AF_INET,SOCK_STREAM,0);   
        if(gStreamServerFd == -1 ){  
            ERR("ERROR in create Stream Socket!\n");  
            return -1;  
        }  
        memset(&server,0,sizeof(server));  
        server.sin_family = AF_INET;  
        server.sin_port = htons(PORT_SOCKET);  
        server.sin_addr.s_addr = htonl(INADDR_ANY);  
        /*绑定监听端口*/  
        if(bind(gStreamServerFd ,(struct sockaddr*)&server,sizeof(server))== -1){  
            ERR("ERROR in bind Stream Socket: %s\n",strerror(errno));  
            return -1;  
        }  
        /*开始监听*/  
        if( listen(gStreamServerFd, 5) == -1){  
            ERR("ERROR in listen Stream Socket: %s\n",strerror(errno));  
            return -1;  
        }  
        /*创建socket连接线程,用来处理监听的结果,比如有客户端连接等*/  
        pthread_create(&tStreamSocketThr,NULL,SocketThread,NULL);  
        /*release thread resource,so we not use pthread_join to waitting*/  
        pthread_detach(tStreamSocketThr);  
        return 0;  
    }  
      
    #if 1  
    int main()  
    {  
        if(SocketInit() == -1){  
            return -1;  
        }  
        while(1){  
            sleep(2);  
        }  
          
        /*notice to exit*/  
        isStreamQuit = -1;  
        sleep(1);  
        if(gStreamServerFd){  
            close(gStreamServerFd);  
        }  
        DBG("SUCCESS in ConnectManageExit\n");  
    }  
    #endif   


运行结果

[cpp] view plain copy

    [root@localhost src]# ./socket_connect  
    accep a stream client  
    rcvLen: 7,rcvBuf: helle 1  
    Close Stream Socket  
    accep a stream client  
    rcvLen: 7,rcvBuf: hello 2  
    Close Stream Socket  
    accep a stream client  
    rcvLen: 7,rcvBuf: hello 3  
    rcvLen: 7,rcvBuf: hello 4  
    rcvLen: 7,rcvBuf: helle 5  
    Close Stream Socket  
复制代码

 





本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/7211790.html,如需转载请自行联系原作者

相关文章
|
Java API 微服务
为什么虚拟线程将改变Java并发编程?
为什么虚拟线程将改变Java并发编程?
559 83
|
11月前
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
370 6
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
665 16
|
11月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
889 0
|
弹性计算 安全 Linux
阿里云服务器ECS安装宝塔Linux面板、安装网站(新手图文教程)
本教程详解如何在阿里云服务器上安装宝塔Linux面板,涵盖ECS服务器手动安装步骤,包括系统准备、远程连接、安装命令执行、端口开放及LNMP环境部署,手把手引导用户快速搭建网站环境。
|
Java Linux 网络安全
Linux云端服务器上部署Spring Boot应用的教程。
此流程涉及Linux命令行操作、系统服务管理及网络安全知识,需要管理员权限以进行配置和服务管理。务必在一个测试环境中验证所有步骤,确保一切配置正确无误后,再将应用部署到生产环境中。也可以使用如Ansible、Chef等配置管理工具来自动化部署过程,提升效率和可靠性。
1167 13
|
监控 Linux 网络安全
FinalShell SSH工具下载,服务器管理,远程桌面加速软件,支持Windows,macOS,Linux
FinalShell是一款国人开发的多平台SSH客户端工具,支持Windows、Mac OS X和Linux系统。它提供一体化服务器管理功能,支持shell和sftp同屏显示,命令自动提示,操作便捷。软件还具备加速功能,提升访问服务器速度,适合普通用户和专业人士使用。
3949 0
|
存储 安全 Linux
Linux服务器上安装配置GitLab的步骤。
按照以上步骤,一个基础的GitLab服务应该运行并可以使用。记得定期检查GitLab官方文档,因为GitLab的安装和配置步骤可能随着新版本而变化。
1115 0
|
机器学习/深度学习 消息中间件 存储
【高薪程序员必看】万字长文拆解Java并发编程!(9-2):并发工具-线程池
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的强力并发工具-线程池,废话不多说让我们直接开始。
484 0
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
365 26