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,如需转载请自行联系原作者

相关文章
|
16天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
16天前
|
程序员 开发者 Python
Python网络编程基础(Socket编程) 错误处理和异常处理的最佳实践
【4月更文挑战第11天】在网络编程中,错误处理和异常管理不仅是为了程序的健壮性,也是为了提供清晰的用户反馈以及优雅的故障恢复。在前面的章节中,我们讨论了如何使用`try-except`语句来处理网络错误。现在,我们将深入探讨错误处理和异常处理的最佳实践。
|
20天前
|
网络协议 程序员 Python
pythonTCP客户端编程创建Socket对象
【4月更文挑战第6天】本教程介绍了TCP客户端如何创建Socket对象。Socket作为网络通信的基础单元,包含协议、IP地址和端口等信息。在TCP/IP中,Socket分为流式(TCP)、数据报(UDP)和原始套接字。以Python为例,创建TCP Socket对象需调用`socket.socket(AF_INET, SOCK_STREAM)`。为确保健壮性,应使用异常处理处理可能的`socket.error`。学习本教程将帮助你掌握TCP客户端创建Socket对象的技能。
|
1月前
|
网络协议 Linux C语言
Linux实现socket网络通信
Linux实现socket网络通信
|
1月前
|
网络协议 安全 API
计算机网络之Socket编程
计算机网络之Socket编程
|
1月前
|
监控 安全 Unix
UNIX域套接字(Unix Domain Socket)在安全性和隐私性
UNIX域套接字(Unix Domain Socket)在安全性和隐私性
47 2
|
15天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
39 6
|
1月前
|
存储 安全 数据管理
Linux系统编程教程之Linux线程函数的使用:讲解Linux线程函数
Linux系统编程教程之Linux线程函数的使用:讲解Linux线程函数
19 1
|
2天前
|
存储 网络协议 关系型数据库
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
|
3天前
|
固态存储 Ubuntu Linux
Linux(29) 多线程快速解压缩|删除|监视大型文件
Linux(29) 多线程快速解压缩|删除|监视大型文件
11 1