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
时间: 2024-08-25 22:48:55

jchat:linux聊天程序3:服务器的相关文章

jchat:linux聊天程序1:简介

做一个linux的聊天软件,虽然没什么创意,但是它可以用来锻炼和测试我对网络编程的掌握程度,也借此机会做一些有意思的程序. 这里做的是linux下一个命令行的客户端与服务器的聊天程序,没写界面,因为对qt不太熟,纯命令行朴素点,但是对于网络编程使用到就足够了. 这个程序实现了基本的用户注册登录功能,信息发送与接收功能,未读信息存入数据库并在用户登录时获取. 另外,使用了mysql作为存储的数据库,存储着用户注册的信息与用户之间发送的消息. 服务器负责接收客户端的一切请求,对于每个客户端进程都新建

jchat:linux聊天程序2:MySQL

该软件使用的数据库为MySQL,因为它免费.开源,在linux下几乎就是最好的选择. 首先要在mysql中root用户新建数据库并赋权给本用户: 1 create database jchat; 2 grant all on jchat.* to 'huanglianjing'; 然后登录mysql的huanglianjing用户添加数据表: 用户表: 1 create table user 2 ( 3 user varchar(20) not null, 4 passwd varchar(20

jchat:linux聊天程序4:客户端

makefile: jchat: main.o login.o regist.o tcp.o gcc -w main.o login.o regist.o tcp.o -o jchat rm -f *.o *.gch *~ main.o: main.c login.h regist.h tcp.h gcc -w -c main.c login.h regist.h tcp.h login.o: login.c login.h tcp.h gcc -w -c login.c login.h tcp

Linux 下基于多线程服务器/客服端聊天程序源码

Linux 下基于多线程服务器/客服端聊天程序,采用阻塞的socket技术,和多线程技术实现. 客服端程序:client.c #include<stdio.h> #include<stdlib.h> #include<string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h>

一个hello/hi的简单的网络聊天程序和python Socket API与Linux Socket API之间的关系

1.Socket概述 套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开.读写和关闭等操作.套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信.网络套接字是IP地址与端口的组合. 套接字可以看成是两个网络应用程序进行通信时,各自通信连接中的一个端点.通信时,其中的一个网络应用程序将要传输的一段信息写入它所在主机的Socket中,该Socket通过网络接口卡的传输介质将这段信息发送给另一台主机的Socket中,使这段信息能传送到

通过基于java实现的网络聊天程序分析java中网络API和Linux Socket API关系

1. 引言 socket网络编程,可以指定不同的通信协议,在这里,我们使用TCP协议实现基于java的C/S模式下“hello/hi”网络聊天程序 2. 目标 1). 通过该网络聊天程序,了解java Socket API接口的基本用法 2). java Socket API简要介绍 3). linux socket API 简单分析 4). tcp协议的连接和终止 5). 探究java socket API 和 linux socket api之间的关系 3. linux socket API

Linux下C语言多线程,网络通信简单聊天程序

原文:Linux下C语言多线程,网络通信简单聊天程序 功能描述:程序应用多线程技术,可是实现1对N进行网络通信聊天.但至今没想出合适的退出机制,除了用Ctr+C.出于演示目的,这里采用UNIX域协议(文件系统套接字),程序分为客户端和服务端.应用select函数来实现异步的读写操作. 先说一下服务端:首先先创建套接字,然后绑定,接下进入一个无限循环,用accept函数,接受“连接”请求,然后调用创建线程函数,创造新的线程,进入下一个循环.这样每当有一个新的“连接”被接受都会创建一个新的线程,实现

Node.js + Web Socket 打造即时聊天程序嗨聊

前端一直是一块充满惊喜的土地,不仅是那些富有创造性的页面,还有那些惊赞的效果及不断推出的新技术.像node.js这样的后端开拓者直接将前端人员的能力扩大到了后端.瞬间就有了一统天下的感觉,来往穿梭于前后端之间代码敲得飞起,从此由前端晋升为'前后端'. 图片来自G+ 本文将使用Node.js加web socket协议打造一个网页即时聊天程序,取名为HiChat,中文翻过来就是'嗨聊',听中文名有点像是专为寂寞单身男女打造的~ 其中将会使用到express和socket.io两个包模块,下面会有介绍

利用java的Socket实现一个简单hello/hi聊天程序

利用java的Socket实现一个简单hello/hi聊天程序 首先,我们来用java实现一个简单的hello/hi聊天程序.在这个程序里,我学习到了怎么用socket套接套接字来进行编程.简单理解了一些关于socket套接字和底层调用的关系.关于java的封装思想,我学会了一些东西,java里真的是万物皆对象.还学到了一点多线程的知识. TCP 在这里,不得不先介绍以下TCP.TCP是传输层面向连接的协议.提供了端到端的进程之间的通信方式.TCP在通信之前要先建立连接.这里我们称这个建立连接的