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

相关文章
|
3月前
|
安全 Linux Shell
Linux上执行内存中的脚本和程序
【9月更文挑战第3天】在 Linux 系统中,可以通过多种方式执行内存中的脚本和程序:一是使用 `eval` 命令直接执行内存中的脚本内容;二是利用管道将脚本内容传递给 `bash` 解释器执行;三是将编译好的程序复制到 `/dev/shm` 并执行。这些方法虽便捷,但也需谨慎操作以避免安全风险。
223 6
|
4月前
|
网络协议 Linux
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
723 2
|
2月前
|
Python
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
使用Python的socket库实现客户端到服务器端的图片传输,包括客户端和服务器端的代码实现,以及传输结果的展示。
173 3
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
|
2月前
|
JSON 数据格式 Python
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
本文介绍了如何使用Python的socket模块实现客户端到服务器端的文件传输,包括客户端发送文件信息和内容,服务器端接收并保存文件的完整过程。
184 1
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
|
2月前
|
运维 Java Linux
【运维基础知识】Linux服务器下手写启停Java程序脚本start.sh stop.sh及详细说明
### 启动Java程序脚本 `start.sh` 此脚本用于启动一个Java程序,设置JVM字符集为GBK,最大堆内存为3000M,并将程序的日志输出到`output.log`文件中,同时在后台运行。 ### 停止Java程序脚本 `stop.sh` 此脚本用于停止指定名称的服务(如`QuoteServer`),通过查找并终止该服务的Java进程,输出操作结果以确认是否成功。
76 1
|
2月前
|
网络协议 Linux 网络性能优化
Linux基础-socket详解、TCP/UDP
综上所述,Linux下的Socket编程是网络通信的重要组成部分,通过灵活运用TCP和UDP协议,开发者能够构建出满足不同需求的网络应用程序。掌握这些基础知识,是进行更复杂网络编程任务的基石。
179 1
|
3月前
|
消息中间件 分布式计算 Java
Linux环境下 java程序提交spark任务到Yarn报错
Linux环境下 java程序提交spark任务到Yarn报错
51 5
|
4月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
155 0
|
2天前
|
人工智能 JSON Linux
利用阿里云GPU加速服务器实现pdf转换为markdown格式
随着AI模型的发展,GPU需求日益增长,尤其是个人学习和研究。直接购置硬件成本高且更新快,建议选择阿里云等提供的GPU加速型服务器。
利用阿里云GPU加速服务器实现pdf转换为markdown格式
|
2天前
|
开发框架 缓存 .NET
阿里云轻量应用服务器、经济型e、通用算力型u1实例怎么选?区别及选择参考
在阿里云目前的活动中,价格比较优惠的云服务器有轻量应用服务器2核2G3M带宽68元1年,经济型e实例2核2G3M带宽99元1年,通用算力型u1实例2核4G5M带宽199元1年,这几个云服务器是用户关注度最高的。有的新手用户由于是初次使用阿里云服务器,对于轻量应用服务器、经济型e、通用算力型u1实例的相关性能并不是很清楚,本文为大家做个简单的介绍和对比,以供参考。

热门文章

最新文章