• Linux多人群聊系统(简单多线程服务器)


    一:要求

      1.通过一个服务器实现最多5个客户之间的信息群发。

      2.服务器显示客户的登录与退出;

      3.客户连接后首先发送客户名称,之后发送群聊信息;

      4.客户输入bye代表退出,在线客户能显示其他客户的登录于退出。

    二:提示

    1、服务器端:

      主线程:

        定义一个全局客户信息表ent,每个元素对应一个客户,存储:socket描述符、客户名、客户IP、客户端口、状态(初值为0)。

        主线程循环接收客户连接请求,在ent中查询状态为0的元素,

            如果不存在状态为0的元素(即连接数超过最大连接数),向客户发送EXIT标志;

            否则,修改客户信息表中该元素的socket描述符、客户IP、客户端口号,状态为1(表示socket可用);

        同时创建一个通信线程并将客户索引号index传递给通信线程。

      通信线程:

        首先向客户端发送OK标志

        循环接收客户发来信息,若信息长度为0,表示客户端已关闭,向所有在线客户发送该用户退出;

        若信息为用户名,修改全局客户信息表ent中index客户的用户名name,并显示该用户登录;

        若信息为退出,修改全局客户信息表ent中index客户状态为0,并显示该用户退出,终止线程;

        同时查询全局客户信息表ent,向状态为1的客户发送接收的信息。

    2、客户端:

        根据用户从终端输入的服务器IP地址及端口号连接到相应的服务器;

        连接成功后,接收服务端发来的信息,若为EXIT,则达到最大用户量,退出;

        若为OK,可以通讯,首先先发送客户名称;

        主进程循环从终端输入信息,并将信息发送给服务器;

        当发送给服务器为bye后,程序退出。

        同时创建一个线程负责接收服务器发来的信息,并显示,当接收的长度小于等于0时终止线程;

     

    三:程序

         客户端与服务端的头文件:       

    ifndef _GCS_H
    #define _GCS_H
    #include <netinet/in.h>
    
    
    #define MSGLEN  1024
    
    #define OK   1
    #define EXIT 2
    #define MSG  3
    #define USER 4
    
    
    
    struct CLIENTMSG {
        int op;
        char user[20];
        char buf[MSGLEN];
    };
    
    struct CLIENTS {
        int sockfd;
        int port;
        char user[20];
        struct sockaddr_in client;
        int stat;
    };
    struct CLIENTS ent[5];
    
    
    
    #endif

      

          服务端:

      

    #include <stdio.h>  
    #include <stdlib.h>     
    #include <string.h>  
    #include <errno.h>  
    #include <sys/socket.h>  
    #include <arpa/inet.h>  
    #include <netinet/in.h>  
    #include <sys/types.h>  
    #include <unistd.h> 
    #include <fcntl.h>
    #include <sys/ipc.h>
    #include <pthread.h>
    #include "group_chat_system.h"
    
    extern struct CLIENTS ent[5];
    
    
    void* func(void *arg);
    void sever_process(int index);
    
    
    int main(int argc, char **argv)
    {
        int sever_fd,client_fd;
        struct sockaddr_in sever,client;
        char ip[20];
        int port,clientlen;
        unsigned char i,index;
        struct CLIENTMSG clientMSG;
        pthread_t tid;
        int *arg;
    
        for(i=0; i<5; i++) {
            ent[i].stat = 0;
        }
    
        /***************创建服务器sockfd************/
        if((sever_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            perror("socket error");
            exit(errno);
        }
    
        /***************输入ip与端口*****************/
        printf("please input ip:");
        scanf("%s", ip);
        printf("
    please input port:");
        scanf("%d", &port);
        printf("
    ");
    
        /******************bind***********************/
        bzero(&sever, sizeof(sever));
        sever.sin_family = AF_INET;
        sever.sin_port   = htons(port);
        sever.sin_addr.s_addr= inet_addr(ip);
        if(bind(sever_fd, (struct sockaddr*)&sever, sizeof(struct sockaddr)) == -1) {
            perror("bind error");
            exit(errno);
        }
    
       /******************listen***********************/
       if(listen(sever_fd, 5) == -1) {
            perror("listen error");
            exit(errno);
       }
        
       while(1) {
        clientlen = sizeof(client);
        if((client_fd = accept(sever_fd, (struct sockaddr*)&client, &clientlen)) == -1) {
            perror("accept error");
            exit(errno);
        }
        printf("accept ok
    ");
        index = 5;
        for(i=0; i<5; i++) {
            if(ent[i].stat ==0){
                index = i;
                break;
          }
        }
    
        if(index <= 4) {
            printf("client_fd : %d
    ", client_fd);
            ent[index].sockfd = client_fd;
            ent[index].port   = port;
            ent[index].client = client;
            ent[index].stat   = 1;
            arg = malloc(sizeof(int));
            *arg = index;
            pthread_create(&tid, NULL, func, (void*)arg);
        } else {
            printf("the client already has 5
    ");
            bzero(&clientMSG, sizeof(clientMSG));
            clientMSG.op = EXIT;
            send(client_fd, &clientMSG, sizeof(clientMSG), 0);
            close(client_fd);
        }
    
       }
        close(sever_fd);
        return 0;
    }
    
    
    void *func(void *arg) 
    {
        int *info;
        info = (int *)arg;
        sever_process(*info);
        pthread_exit(NULL);
    }
    
    void sever_process(int index)
    {
        struct CLIENTMSG sendMSG;
        struct CLIENTMSG recvMSG;
        int len,i;
    
        /*首先发送邋OK标志*/
        sendMSG.op = OK;
        send(ent[index].sockfd, &sendMSG, sizeof(sendMSG), 0);
    
        while(1) {
            bzero(&sendMSG, sizeof(sendMSG));
            bzero(&recvMSG, sizeof(recvMSG));
    
            len = recv(ent[index].sockfd, &recvMSG, sizeof(recvMSG), 0);
            if(len == 0) {
                sendMSG.op = EXIT;
                for(i=0; i<5; i++) {
                    if(ent[i].stat == 1)
                        send(ent[i].sockfd, &sendMSG, sizeof(sendMSG), 0);
                }
            }
            if(len > 0) {
                if(recvMSG.op == USER) {
                    bcopy(recvMSG.user, ent[index].user, strlen(recvMSG.user));
                    printf("user %s login form ip: %s   port: %d
    ", ent[index].user, inet_ntoa(ent[index].client.sin_addr), ntohs(ent[index].client.sin_port));
                    sendMSG.op = USER;
                }
                if(recvMSG.op == EXIT) {
                    //printf("recv exit
    ");
                    sendMSG.op = EXIT;
                    bcopy(ent[index].user, sendMSG.user, strlen(recvMSG.user));
                    for(i=0; i<5; i++) {
                        if(ent[i].stat == 1)
                            send(ent[i].sockfd, &sendMSG, sizeof(sendMSG), 0);
                    }
                    break;
                }
                if(recvMSG.op == MSG) {
                    //printf("recv msg
    ");
                    //printf("%s: %s", recvMSG.user,recvMSG.buf);
                    sendMSG.op= MSG;
                }    
                bcopy(recvMSG.user, sendMSG.user, strlen(recvMSG.user));
                bcopy(recvMSG.buf, sendMSG.buf, strlen(recvMSG.buf));
                for(i=0; i<5; i++) {
                    //printf("
    %d: %s
    ", sendMSG.op, sendMSG.user);
                    if(ent[i].stat == 1) {
                        if(strncmp(ent[i].user, sendMSG.user, strlen(sendMSG.user)))
                            send(ent[i].sockfd, &sendMSG, sizeof(sendMSG), 0);
                    }
                        
                }    
            }
        }
    
    }

        

      客户端:

    #include <stdio.h>  
    #include <stdlib.h>     
    #include <string.h>  
    #include <errno.h>  
    #include <sys/socket.h>  
    #include <arpa/inet.h>  
    #include <netinet/in.h>  
    #include <sys/types.h>  
    #include <unistd.h> 
    #include <fcntl.h>
    #include <sys/ipc.h>
    #include <pthread.h>
    #include "group_chat_system.h"
    
    
    struct client_arg {
        int sockfd;
        struct CLIENTMSG clientMSG;
    };
    struct client_arg *arg;
    
    void *func(void* arg);
    void client_process(int sockfd, struct CLIENTMSG clientMSG);
    
    int main(int argc, char **argv)
    {
        int sockfd;
        struct sockaddr_in sever;
        char ip[20];
        unsigned int port,len;
        struct CLIENTMSG sendMSG;
        pthread_t tid;
    
        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            perror("socket error");
            exit(1);
        }
    
        printf("please input ip:");
        scanf("%s", ip);
        printf("
    please input port:");
        scanf("%d", &port);
        printf("
    ");
    
        bzero(&sever, sizeof(sever));
        sever.sin_family = AF_INET;
        sever.sin_port = htons(port);
        inet_aton(ip, &sever.sin_addr);
        if(connect(sockfd, (struct sockaddr*)&sever, sizeof(struct sockaddr)) == -1) {
            perror("connect error");
            exit(errno);
        }
    
        len = recv(sockfd, &sendMSG, sizeof(sendMSG), 0);
        if(len > 0){
            if(sendMSG.op == EXIT) {
                printf("exceed the numble of users
    ");
            }
            if(sendMSG.op == OK) {
                bzero(&sendMSG, sizeof(sendMSG));
                printf("please input client name: ");
                fgets(sendMSG.user, MSGLEN, stdin);
                //scanf("%s", sendMSG.user);
                sendMSG.op = USER;
                send(sockfd, &sendMSG, sizeof(sendMSG), 0);
                arg = (struct client_arg*)malloc(sizeof(struct client_arg));
                arg->sockfd = sockfd;
                pthread_create(&tid, NULL, func, (void*)arg);
    
                while(1) {
    //                bzero(&sendMSG, sizeof(sendMSG));
                    sendMSG.op = MSG;
                    //printf("waiting...");
                    fgets(sendMSG.buf, MSGLEN, stdin);
                    //scanf("%s", sendMSG.buf);
                    //printf("%s: %s  %d
    ", sendMSG.user,sendMSG.buf, sendMSG.op);
                    if(!strncasecmp(sendMSG.buf, "bye", 3)) {
                        sendMSG.op = EXIT;
                        send(sockfd, &sendMSG, sizeof(sendMSG), 0);
                        break;
                    }
                    send(sockfd, &sendMSG, sizeof(sendMSG), 0);
                }
            }
            pthread_cancel(tid);
        }
        close(sockfd);
        return 0;
    }
    
    void *func(void* arg)
    {
        struct client_arg *info;
        info = (struct client_arg*)arg;
        client_process(info->sockfd, info->clientMSG);
        free(arg);
        pthread_exit(NULL);
    }
    
    void client_process(int sockfd, struct CLIENTMSG clientMSG)
    {
        int len;
        while(1) {
            bzero(&clientMSG, sizeof(clientMSG));
            len = recv(sockfd, &clientMSG, sizeof(clientMSG), 0);
            if(len > 0) {
                if(clientMSG.op==USER){
                    printf("the user %s is login.
    ",clientMSG.user);
                 }else if(clientMSG.op == EXIT){
                     printf("the user %s is logout.
    ",clientMSG.user);
                 }else if(clientMSG.op == MSG){
                    printf("%s: %s
    ",clientMSG.user,clientMSG.buf);
                }
            }
        }
    }

      Makefile文件:

      

    main:sever.o client.o
            gcc sever.o -o sever -lpthread
            gcc client.o -o client -lpthread
    sever.o:sever.c
            gcc -c sever.c group_chat_system.h
            gcc -c client.c group_chat_system.h
    clean:
            rm *.o sever client

    四:现象

      

     

     

  • 相关阅读:
    Java之三元运算符
    Linux之用户和用户组管理指令
    Java之键盘输入语句Scanner
    进程同步和进程互斥
    Java之运算符优先级
    Java之单分支和双分支程序流程基本使用
    Python chr 函数 Python零基础入门教程
    Python globals 函数 Python零基础入门教程
    Python filter 函数 Python零基础入门教程
    Python locals 函数 Python零基础入门教程
  • 原文地址:https://www.cnblogs.com/qigaohua/p/5688998.html
Copyright © 2020-2023  润新知