jchat:linux聊天程序3:服务器

makefile:

jchat_server:    main.o process.o sql.o

    gcc -o jchat_server main.o process.o sql.o -L/usr/lib/mysql -lmysqlclient

    rm -f *.o *.gch *~

main.o:            main.c process.h sql.h

    gcc -c main.c process.h sql.h -I/usr/include/mysql

process.o:        process.h process.h

    gcc -c process.c process.h -I/usr/include/mysql

sql.o:            sql.c sql.h

    gcc -c sql.c sql.h -I/usr/include/mysql



clean:

    rm -f *.o *.gch *~ jchat_server

 

main.c:主函数

/*server/main.c*/



#include <stdlib.h>

#include <string.h>

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/un.h>

#include <netinet/in.h>



#include "process.h"

#include "sql.h"



#define MAXLINE 4096

#define LISTENQ 1024

#define PORT 12345



int listenfd;

pid_t pid_online_time, pid_conn;



/*

 * init server create socket

 */

void server_init()

{

    listenfd = socket(AF_INET, SOCK_STREAM, 0);



    struct sockaddr_in servaddr;

    memset(&servaddr, 0, sizeof(servaddr));

    servaddr.sin_family = AF_INET;

    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    servaddr.sin_port = htons(PORT);



    bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));



    listen(listenfd, LISTENQ);

}



int main(int argc, char *argv[])

{

    server_init();



    pid_online_time = fork();

    if (pid_online_time == 0) {

        refresh_online_time();

    }



    while (1) {

        struct sockaddr_in cliaddr;

        int clilen = sizeof(cliaddr);



        int connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);



        if ((pid_conn = fork()) == 0) {

            close(listenfd);

            process(connfd);

        }

        else {

            pid_t pid = getpid();

            //printf("fork process pid = %d\n", pid);

        }



        close(connfd);

    }



    exit(0);

}

 

process.c:一个子进程用于处理一个客户端发来的所有请求

/*server/process.c*/



#include <stdlib.h>

#include <string.h>

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/un.h>

#include <netinet/in.h>

#include <my_global.h>

#include <my_sys.h>

#include <mysql.h>



#include "process.h"

#include "sql.h"



#define MAXLINE 4096



char sendbuff[MAXLINE], recvbuff[MAXLINE];

int recv_len;



/*

 * all users' online time - 1 every second

 */

void refresh_online_time()

{

    MYSQL *conn = sql_init();



    while (1) {

        mysql_query(conn, "update jchat.user set online_time=online_time-1 \

                    where online_time>0;");

        //printf("refresh online time -1\n");

        sleep(1);

    }

}



/*

 * regist new user

 * fail when user exists already

 */

void regist(int sockfd)

{

    MYSQL *conn = sql_init();



    int i, j, k, l;

    i = 2;j = 3;

    while (recvbuff[j] != ':') ++j;

    k = j + 1;

    char user[30], passwd[30];

    for (l=i; l<j; ++l) {

        user[l-i] = recvbuff[l];

    }

    user[j-i] = '\0';

    for (l=k; l<recv_len; ++l) {

        passwd[l-k] = recvbuff[l];

    }

    user[recv_len-k] = '\0';



    char query[107];

    sprintf(query, \

            "select * from jchat.user where user='%s';", \

            user);

    mysql_query(conn, query);



    MYSQL_RES *res = mysql_use_result(conn);

    MYSQL_ROW row = mysql_fetch_row(res);

    if (row != NULL) { // exist user

        sendbuff[0] = 'n';sendbuff[1] = '\0';

    }

    else {

        sendbuff[0] = 'y';sendbuff[1] = '\0';

        sprintf(query, \

                "insert into jchat.user values('%s','%s',0);", \

                user, passwd);

        mysql_query(conn, query);

    }

    mysql_free_result(res);



    write(sockfd, sendbuff, strlen(sendbuff));

    //printf("sendbuff> '%s'\n", sendbuff);



    sql_exit(conn);



    printf("regist user=%s passwd=%s\n", user, passwd);

}



/*

 * login a user

 * fail if user and password not match

 */

void login(int sockfd)

{

    MYSQL *conn = sql_init();



    int i, j, k, l;

    i = 2;j = 3;

    while (recvbuff[j] != ':') ++j;

    k = j + 1;

    char user[30], passwd[30];

    for (l=i; l<j; ++l) {

        user[l-i] = recvbuff[l];

    }

    user[j-i] = '\0';

    for (l=k; l<recv_len; ++l) {

        passwd[l-k] = recvbuff[l];

    }

    user[recv_len-k] = '\0';



    char query[107];

    sprintf(query, \

            "select * from jchat.user where user='%s' and passwd='%s';", \

            user, passwd);

    mysql_query(conn, query);



    MYSQL_RES *res = mysql_use_result(conn);

    MYSQL_ROW row = mysql_fetch_row(res);

    if (row != NULL) { // user and passwd correct

        sendbuff[0] = 'y';sendbuff[1] = '\0';

        sprintf(query, \

                "update jchat.user set online_time=7 \

                where user='%s';", user);

        mysql_query(conn, query);

    }

    else {

        sendbuff[0] = 'n';sendbuff[1] = '\0';

    }

    mysql_free_result(res);



    write(sockfd, sendbuff, strlen(sendbuff));

    //printf("sendbuff> '%s'\n", sendbuff);



    sql_exit(conn);



    printf("login user=%s passwd=%s\n", user, passwd);

}



/*

 * get user online notice and update online time to 12

 */

void user_at()

{

    MYSQL *conn = sql_init();



    int i;

    char user[21];

    for (i=2; i<recv_len; ++i) {

        user[i-2] = recvbuff[i];

    }

    user[recv_len-2] = '\0';



    char query[107];

    sprintf(query, \

            "update jchat.user set online_time=12 where user='%s';", \

            user);

    mysql_query(conn, query);



    sql_exit(conn);



    //printf("%s is online\n", user);

}



/*

 * return a user's unread message

 * and delete the message in mysql

 */

void get_mesg(int sockfd)

{

    MYSQL *conn = sql_init();



    int i;

    char user[21];

    for (i=2; i<recv_len; ++i) {

        user[i-2] = recvbuff[i];

    }

    user[recv_len-2] = '\0';



    char query[107];

    sprintf(query, \

            "select * from jchat.user where \

            user='%s';", user);

    mysql_query(conn, query);



    MYSQL_RES *res = mysql_use_result(conn);

    MYSQL_ROW row = mysql_fetch_row(res);

    if (row != NULL) { // user exist

        mysql_free_result(res);

        sprintf(query, \

                "select * from jchat.mesg where recvuser='%s';", \

                user);

        mysql_query(conn, query);



        char senduser[30], recvuser[30], text[1007];



        res = mysql_use_result(conn);

        sendbuff[0] = '\0';

        int hasMesg = 0;

        while ((row = mysql_fetch_row(res)) != NULL) {

            hasMesg = 1;

            int row_num = mysql_num_fields(res);

            strcpy(senduser, row[0]);

            strcpy(recvuser, row[1]);

            strcpy(text,     row[2]);



            strcat(sendbuff, senduser);

            strcat(sendbuff, ":"     );

            strcat(sendbuff, text    );

            strcat(sendbuff, ";"     );

        }



        if (!hasMesg) {

            strcpy(sendbuff, ";");

        }



        mysql_free_result(res);



        sprintf(query, \

                "delete from jchat.mesg where recvuser='%s';", \

                user);

        mysql_query(conn, query);



        write(sockfd, sendbuff, strlen(sendbuff));

        //printf("get_mesg sendbuff> '%s'\n", sendbuff);

    }



    sql_exit(conn);



    //printf("%s get message from server\n", user);

}



/*

 * one user send message to another user

 * store to mysql

 */

void send_mesg()

{

    MYSQL *conn = sql_init();



    int i, j, k, x;

    i = 2;j = 3;

    while (recvbuff[j] != ':') ++j;

    ++j;

    k = j + 1;

    while (recvbuff[k] != ':') ++k;

    ++k;

    //printf("i=%d, j=%d, k=%d\n",i,j,k);



    char senduser[30], recvuser[30], text[1007];

    for (x=0; x<j-1-i; ++x) {

        senduser[x] = recvbuff[x+i];

    }

    senduser[j-1-i] = '\0';

    for (x=0; x<k-1-j; ++x) {

        recvuser[x] = recvbuff[x+j];

    }

    recvuser[k-1-j] = '\0';

    for (x=0; x<recv_len-k; ++x) {

        text[x] = recvbuff[x+k];

    }

    text[recv_len-k] = '\0';

    //printf("senduser = '%s'\nrecvuser = '%s'\n", senduser, recvuser);



    int user_exist = 1;



    char query[107];

    sprintf(query, \

            "select * from jchat.user where user='%s';", \

            senduser);

    mysql_query(conn, query);



    MYSQL_RES *res = mysql_use_result(conn);

    MYSQL_ROW row = mysql_fetch_row(res);

    if (row == NULL) { // send user not exist

        user_exist = 0;

    }

    mysql_free_result(res);



    sprintf(query, \

            "select * from jchat.user where user='%s';", \

            recvuser);

    mysql_query(conn, query);



    res = mysql_use_result(conn);

    row = mysql_fetch_row(res);

    if (row == NULL) { // recv user not exist

        user_exist = 0;

    }

    mysql_free_result(res);



    if (user_exist) {

        sprintf(query, \

                "insert into jchat.mesg values('%s','%s','%s');", \

                senduser, recvuser, text);

        mysql_query(conn, query);

    }



    sql_exit(conn);



    printf("%s send message to %s\n", senduser, recvuser);

}



/*

 * return current online users

 */

void online_user(int sockfd)

{

    MYSQL *conn = sql_init();



    mysql_query(conn, "select user from jchat.user where online_time>0;");

    sendbuff[0] = '\0';

    MYSQL_RES *res = mysql_use_result(conn);

    MYSQL_ROW row;

    int hasOnline = 0;

    while ((row = mysql_fetch_row(res)) != NULL) {

        hasOnline = 1;

        strcat(sendbuff, row[0]);

        strcat(sendbuff, ";"   );

       }



    if (!hasOnline) {

        strcpy(sendbuff, ";");

    }



    mysql_free_result(res);



    write(sockfd, sendbuff, strlen(sendbuff));

    //printf("online_user sendbuff> '%s'\n", sendbuff);



    sql_exit(conn);

}



/*

 * user quit

 * update online time to 0

 */

void quit()

{

    MYSQL *conn = sql_init();



    int i;

    char user[21];

    for (i=2; i<recv_len; ++i) {

        user[i-2] = recvbuff[i];

    }

    user[recv_len-2] = '\0';



    char query[107];

    sprintf(query, \

            "update jchat.user set online_time=0 where user='%s';", \

            user);

    mysql_query(conn, query);



    printf("%s quit\n", user);



    sql_exit(conn);

    exit(0); // exit this process

}



void process(int sockfd)

{

    while ((recv_len = read(sockfd, recvbuff, MAXLINE)) > 0) {

        recvbuff[recv_len] = '\0';

        //printf("process recvbuff> '%s'\n", recvbuff);

        switch (recvbuff[0]) {

            case 'r': // regist

                regist(sockfd);

                break;

            case 'l': // login

                login(sockfd);

                break;

            case 'a': // online notice

                user_at();

                break;

            case 'g': // get message

                get_mesg(sockfd);

                break;

            case 's': // send message

                send_mesg();

                break;

            case 'o': // online user check

                online_user(sockfd);

                break;

            case 'q': // quit

                quit();

                break;

        }

    }

}

 

process.h:

/*server/process.h*/



#ifndef PROCESS_H

#define PROCESS_H



#include <my_global.h>

#include <my_sys.h>

#include <mysql.h>



/*

 * refresh online user's online time every minute

 * seemed as offline if online time decrease to 0

 */

void refresh_online_time();



/*

 * process different command from client

 */

void process(int sockfd);



#endif // PROCESS_H

 

sql.c:新建mysql的连接

/*server/sql.h*/



#include <my_global.h>

#include <my_sys.h>

#include <mysql.h>



#include "sql.h"



static char *host_name = "localhost";

static char *user_name = "your mysql user"; // 这里要更换为自己mysql用户的用户名与密码

static char *passwd = "your mysql password";

static unsigned int port_num = 0;

static char *socket_name = NULL;

static char *db_name = "jchat";

static unsigned int flags = 0;



MYSQL *sql_init()

{

    MYSQL *conn;



    MY_INIT("jchat_server");



    if (mysql_library_init(0,NULL,NULL)) {

        fprintf(stderr, "mysql_library_init() failed\n");

        return NULL;

    }



    conn = mysql_init(NULL);

    if (conn == NULL) {

        fprintf(stderr, "mysql_init() failed\n");

        return NULL;

    }



    if (mysql_real_connect(conn,host_name,user_name,passwd,

            db_name,port_num,socket_name,flags) == NULL) {

        fprintf(stderr, "mysql_real_connect() failed\n");

        mysql_close(conn);

        return NULL;

    }



    return conn;

}



void sql_exit(MYSQL *conn)

{

    mysql_close(conn);

    mysql_library_end();

}

 

sql.h:

/*server/sql.h*/



#ifndef SQL_H

#define SQL_H



#include <my_global.h>

#include <my_sys.h>

#include <mysql.h>



/*

 * link to mysql

 * return 1 if succeed, 0 if fail

 */

MYSQL *sql_init();



void sql_exit(MYSQL *conn);



#endif // SQL_H

 

你可能感兴趣的:(linux)