• 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等环境运行。

    待续。。。。

  • 相关阅读:
    silverlight 调用默认打印机
    拿来主意
    关于js智能提示的封装(修订版)
    silverlight 获取文本框焦点
    silverlight Timer
    winform 中写app.config文件时 调试情况下没有改变的原因
    关于asp:GridView和dx:ASPxGridView固定表头的jquery代码封装
    Microsoft Visual Studio 2010的前世今生
    游戏开发之我见
    JS中数组去重
  • 原文地址:https://www.cnblogs.com/sixindev/p/4468893.html
Copyright © 2020-2023  润新知