zoukankan      html  css  js  c++  java
  • Socket和数据库的一些使用---郭雪彬

    最近偶尔有时间,研究了下Socket的使用,虽然不简单,不过还是挺有意思,刚好咱们带头大哥需要我们发檄文,也罢,那就来一篇,废话不多说,直接入正题

    struct sockaddr_in server_addr;
    pthread_mutex_t mut;
    struct kevent events[10];
     //IP地址、端口和协议族
        server_addr.sin_len = sizeof(struct sockaddr_in);
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(SERVER_PORT);
        server_addr.sin_addr.s_addr = inet_addr(ipAddress);
        bzero(&(server_addr.sin_zero),8);
     //创建socket
        int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (server_sock_fd == -1) {
            perror("socket error");
            return NULL;
        }
        int on=1;
        if((setsockopt(server_sock_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))<0)
        {
            perror("setsockopt failed");
            exit(EXIT_FAILURE);
        }
        //绑定socket
        int bind_result = bind(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
        if (bind_result == -1) {
            perror("bind error");
            return NULL;
        }
        
        
        //监听
        if (listen(server_sock_fd, BACKLOG) == -1) {
            perror("listen error");
            return NULL;
        }
        struct timespec timeout = {10,0};
        //kqueue
        int kq = kqueue();
        if (kq == -1) {
            perror("创建kqueue出错!
    ");
            exit(1);
        }
    struct kevent event_change;
        EV_SET(&event_change, STDIN_FILENO, EVFILT_READ, EV_ADD, 0, 0, NULL);
        kevent(kq, &event_change, 1, NULL, 0, NULL);
        EV_SET(&event_change, server_sock_fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
        kevent(kq, &event_change, 1, NULL, 0, NULL);
        
        while (1) {
    
            int ret = kevent(kq, NULL, 0, events, 10, &timeout);
            if (ret < 0) {
                printf("kevent 出错!
    ");
                continue;
            }else if(ret == 0){
                printf("kenvent 超时!
    ");
                continue;
            }else{
                //ret > 0 返回事件放在events中
                for (int i = 0; i < ret; i++) {
                    struct kevent current_event = events[i];
                    //kevent中的ident就是文件描述符
                    if (current_event.ident == STDIN_FILENO) {
                        //标准输入
                        bzero(input_msg, BUFFER_SIZE);
                        fgets(input_msg, BUFFER_SIZE, stdin);
                        //输入 ".quit" 则退出服务器
                        if (strcmp(input_msg, QUIT_CMD) == 0) {
                            exit(0);
                        }
                        for (int i=0; i<CONCURRENT_MAX; i++) {
                            if (client_fds[i]!=0) {
                                send(client_fds[i], input_msg, BUFFER_SIZE, 0);
                            }
                        }
                    }else if(current_event.ident == server_sock_fd){
                        //有新的连接请求
                        struct sockaddr_in client_address;
                        socklen_t address_len;
                        int client_socket_fd = accept(server_sock_fd, (struct sockaddr *)&client_address, &address_len);
                        if (client_socket_fd > 0) {
                            int index = -1;
                            for (int i = 0; i < CONCURRENT_MAX; i++) {
                                if (client_fds[i] == 0) {
                                    index = i;
                                    client_fds[i] = client_socket_fd;
                                    break;
                                }
                            }
                            if (index >= 0) {
                                EV_SET(&event_change, client_socket_fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
                                kevent(kq, &event_change, 1, NULL, 0, NULL);
                                printf("新客户端(fd = %d)加入成功 %s:%d 
    ",client_socket_fd,inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
                                /*客户端赋值*/
                                strcpy(client.ipAddress, inet_ntoa(client_address.sin_addr));
                                client.client_port = ntohs(client_address.sin_port);
                                client.client_ID = client_socket_fd;
                                
                                /*收集客户端信息并且存储到列表中*/
    //                            if (AddClient(client, &clientList) == false) {
    //                                fprintf(stderr, "Problem allcating memory
    ");
    //                                break;
    //                            }
    //                            if(ListIsFull(&clientList))
    //                            {
    //                                puts("The list is now full.
    ");
    //                                break;
    //                            }
    //                            if(ListIsEmpty(&clientList))
    //                            {
    //                                printf("NO client Connection");
    //                            }else
    //                            {
    //                                Traverse(&clientList, showClients);
    //                            }
    //                            printf("在线客户端人数:%d
    ", ListClientCount(&clientList));
                                
                                
                                if(!QueueIsFull(&line))
                                {
                                    client.client_ID = client_socket_fd;
                                    client.client_port = ntohs(client_address.sin_port);
                                    strcpy(client.ipAddress, inet_ntoa(client_address.sin_addr));
                                    EnQueue(client, &line); //将客户端添加到队列中
                                    char msg[250];
                                    char wellcome[250];
                                    
                                    sprintf(msg,"新客户端(fd = %d) 加入成功 %s:%d",client_socket_fd,inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
                                    
                                    sprintf(wellcome, "WellComm To NB Socket Server System your fd is %d addr is %s and port is %d",client_socket_fd,inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
                                    
                                    //给所有客户端发送消息,除了刚刚连接上的客户端之外
                                    for(int i=0; i<QueueItemCount(&line); i++)
                                    {
                                        
                                        if(index != i)
                                        {
                                            send(client_fds[i], msg, BUFFER_SIZE, 0);
                                        }else
                                        {
                                            send(client_fds[i], wellcome, BUFFER_SIZE, 0);
                                        }
                                    }
                                }
                                
                            }else{
                                
                                bzero(input_msg, BUFFER_SIZE);
                                strcpy(input_msg, "服务器加入的客户端数达到最大值,无法加入!
    ");
                                send(client_socket_fd, input_msg, BUFFER_SIZE, 0);
                                printf("客户端连接数达到最大值,新客户端加入失败 %s:%d 
    ",inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
                                
                            }
                        }
                    }else{
                        //处理某个客户端过来的消息
                        bzero(recv_msg, BUFFER_SIZE);
                        long byte_num = recv((int)current_event.ident,recv_msg,BUFFER_SIZE,0);
                        if (byte_num > 0) {
                            if (byte_num > BUFFER_SIZE) {
                                byte_num = BUFFER_SIZE;
                            }
                            recv_msg[byte_num] = '';
                            printf("客户端(fd = %d):%s
    ",(int)current_event.ident,recv_msg);
                            
                            char delims[] = " ";
                            char *result = NULL;
    
                            result = strtok(recv_msg, delims);
                            int k = 0;
                            while( result != NULL ) {
                                if(k==0)
                                {
                                    strcpy(tableName, result);
    
                                }else if (k == 1)
                                {
                                    strcpy(userID, result);
    
                                }
                            
                                k++;
                                printf( "result is "%s
    ", result );
                                result = strtok( NULL, delims );
                            }
                                sendMessage(client_fds[0], tableName, userID, user, &line);
                            break;
                        }else if(byte_num < 0){
                            printf("从客户端(fd = %d)接受消息出错.
    ",(int)current_event.ident);
                        }else{
                            EV_SET(&event_change, current_event.ident, EVFILT_READ, EV_DELETE, 0, 0, NULL);
                            kevent(kq, &event_change, 1, NULL, 0, NULL);
                            close((int)current_event.ident);
                            for (int i = 0; i < CONCURRENT_MAX; i++) {
                                if (client_fds[i] == (int)current_event.ident) {
                                    
                                    Client *exitClient = (Client *)malloc(sizeof(Client));
                                    
                                    exitClient->client_ID = (int)current_event.ident;
                                    
    //                                selectClientWithFds((int)current_event.ident, &line);
    //                                int count = selectAllCilent(&line);//查找所有在线客户端
                                    
    //                           bool   del =  deleteClientFormList(&clientList, *exitClient);
                                    
    //                                printf("%d
    ",del);
                                    
    //                                Traverse(&clientList, showClients);
                                    
    //                                if(!ListIsEmpty(&clientList))
    //                                {
    //                                    printf("
    排序后的元素
    ");
    //                                    int desc = DescClientFromList(&clientList);
    //                                    Traverse(&clientList, showClients);
    //                                    printf("
    逆置后的元素
    ");
    //                                    Reverse(&clientList);
    //                                    Traverse(&clientList, showClients);
    //                                }
    
    //                                printf("在线客户端人数:%d
    ", ListClientCount(&clientList));
                                    
                                    printf("客户端(fd = %d)退出了
    ",(int)current_event.ident);
    //                                printf("剩余在线客户端个数%d
    ",count);
                                    client_fds[i] = 0;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            
        }    return NULL;
       
    }
    void showClients(Client client)
    {
    //    printf("客户端 IP: %s, port is %d, fds is %d
    ",client.ipAddress, client.port, client.fds);
    }
    //void sendClientStates(int clientCount,Queue *pq)
    //{
    //    
    //    
    //}
    
    
    //对接收到的服务端消息进行处理,并且进行回应
    void * sendMessage(int client_fds, char * message, char *userID, struct userTableInfo *userInfo, Queue *pq)
    {
        struct userMessage user = selectUserInfoWithUserID(message, userID);
        printf("username is %s
    ", user.name);
        
        send(client_fds, user.name, BUFFER_SIZE, 0);
        send(client_fds, user.user_id, BUFFER_SIZE, 0);
        send(client_fds, user.birthday, BUFFER_SIZE, 0);
        
        
    //    pthread_mutex_unlock(&mut);
        return NULL;
        
    }

    以上是服务端部分代码,服务端将上线的客户端加入到链表中进行管理,当客户端上线时,服务端根据Socket的消息将客户端有关信息加入到链表中。

    由于所有操作都在同一台计算机中,所以IP地址都是相同的

    下面通过客户端对服务端发送相关指令获取对应的用户信息,该操作是基于客户端的指令,然后服务端通过相应指令对数据库进行查询,由于时间问题,目前该项目还不是很完善。

     

     由于代码都是基于C语言,可以在linux, mac, windows等环境运行。

    待续。。。。

  • 相关阅读:
    vue开发chrome扩展,数据通过storage对象获取
    Vue手动集成less预编译器
    Google Translate寻找之旅
    Javascript Range对象的学习
    Javascript Promises学习
    SublimeText 建立构建Node js系统
    We're sorry but demo3 doesn't work properly without JavaScript enabled. Please enable it to continue.
    npm安装包出现UNMET DEPENDENCY报错
    (转载)命令行说明中格式 尖括号 中括号的含义
    Linux重启网卡服务Failed to start LSB: Bring up/down networking.
  • 原文地址:https://www.cnblogs.com/sixindev/p/4468893.html
Copyright © 2011-2022 走看看