使用socket通信的简易聊天室,使用sqlite3 SOL数据库引擎

使用socket通信的简易聊天室,使用sqlite3 SOL数据库引擎

这是我学习C语言完成的第一个小项目,是一个简易的聊天室,使用socket通信,使用sqlite3进行数据管理,通过多线程实现server同时响应多个client。最近翻以前的笔记,发现有这个项目的记录,写的比较乱,而且写的太过麻烦了,有很多地方可以优化代码结构,.h和.c文件的命名也很不合适(当时瞎取的名字)。但是作为第一次写的C语言小项目,还是很有纪念意义的,留作纪念吧。
话不多说了,代码贴上来:

一、server端

1、chatroom.h

#ifndef CHATROOM_H_
#define CHATROOM_H_

enum  MsgType 
{
	REG=1,
	LOGIN,
	USERLIST,
	SENDMSG,
	SENDFILE,
	BROADCAST,
	BROADCASTFILE,
	KICK,
	FORBIDDEN,
	LIFT,
	LOGOUT,
	RECORD
};

typedef struct 
{
	char type;
	char from[100];//发送者的用户名,不可重复
	char to[100];//接收着的用户名,不可重复
	char data[1000];//最多发送999个字节
	char id[100];
} Msg; //消息不存入链表,聊天用户存入链表

#endif /* CHATROOM_H_ */

2、link.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef LINK_H_
#define LINK_H_

typedef struct 
{
	char uname[10];//不重复
	int sockfd;
	struct Node* prev;
	struct Node* next;
}Node;

typedef struct 
{
	int len;
	Node* head;
	Node* tail;
} LinkList;

Node* createNode(char uname[], int sockfd);

void addFirst(LinkList* flp,char uname[],int sockfd);

/*注销
 * return
 * 0:success
 * -1:failuer
*/
int del(LinkList* flp,char uname[]);

//由用户名从链表中查出对应的sockfd
Node* get(LinkList* flp,char uname[]);

void travel(LinkList* flp);

void userlist(LinkList* flp,char data[]);

#endif /* LINK_H_ */

3、link.c

#include "link.h"

Node* createNode(char uname[], int sockfd)
{
	Node* ptr = malloc(sizeof(Node));
	if(ptr == NULL)
    {
		printf("malloc error!");
		exit(1);
	}
	strcpy(ptr->uname,uname);
	ptr->sockfd = sockfd;
	ptr->prev = NULL;
	ptr->next = NULL;
	return ptr;
}

void addFirst(LinkList* flp,char uname[],int sockfd)
{
	Node* ptr = createNode(uname,sockfd);
	if (flp->len)
    {//非空
		ptr->next = flp->head;
		flp->head->prev = ptr;
		flp->head = ptr;
	}
    else
    {//空
		flp->head = ptr;
		flp->tail = ptr;
	}
	flp->len++;
}

//注销
int del(LinkList* flp,char uname[])
{
	Node* ptr = get(flp,uname);
	if (ptr == NULL)
    {
		printf("Node is not exist!\n");
		return -1;
	}
	if (ptr == flp->head)
    {//是第一个节点
		flp->head = flp->head->next;
	}
    else if (ptr == flp->tail)
    {//最后一个节点
		flp->tail = flp->tail->prev;
	}
    else
    {
		Node* prev = ptr->prev;
		Node* next = ptr->next;
		prev->next = next;
		next->prev = prev;
	}
	free(ptr);
	flp->len--;
	return 0;
}

//由用户名从链表中查出对应的sockfd
Node* get(LinkList* flp,char uname[])
{
	Node* ptr = flp->head;
	while (ptr)
    {
		if (strcmp(ptr->uname,uname)==0)
        {
			return ptr;
		}
		ptr = ptr->next;
	}
	return NULL;
}

void travel(LinkList* flp)
{
	int len = flp->len;
	Node* ptr = flp->head;
	printf(":---------------------------------------\n");
	printf("size = %d\n",len);
	while (len--)
    {
		printf("uname=%s,sockfd=%d\n",ptr->uname,ptr->sockfd);
		ptr = ptr->next;
	}
	printf(":--------------------------------------;\n");
}

void userlist(LinkList* flp,char data[])
{
	int len = flp->len;
	Node* ptr = flp->head;
	char buf[100];
	strcat(data,":---------------------------------------\n");
	sprintf(buf,"size=%d\n",len);
	strcat(data,buf);
	while (len--)
    {
		memset(buf,0,100);
		sprintf(buf,"uname=%s,sockfd=%d\n",ptr->uname,ptr->sockfd);
		strcat(data,buf);
		ptr = ptr->next;
	}
	printf(":--------------------------------------;\n");
}

4、messagedao.h

#ifndef MESSAGEDAO_H_
#define MESSAGEDAO_H_

#include <string.h>
#include <sqlite3.h>

/*
 * return
 * 0:success
 * -1:failure
 */
char addMsg(char from[],char to[],char data[],int type);

char getMsg(char from[],char type);

#endif /* USERDAO_H_ */

5、messagedao.c

#include "userdao.h"
#include <sqlite3.h>
#include <string.h>
#include "messagedao.h"
/*
 * return
 * 0:success
 * -1:failure
 */

char addMsg(char from[],char to[],char data[],int type)
{
	sqlite3* db;
	int ret = sqlite3_open("/home/liuyin/test/source/server/chatroom.db",&db);
	if(ret != SQLITE_OK)
    {
		sqlite3_close(db);
		perror("sqlite3 open error!");
		return -1;
	}

	char* error;
	char sql[100]={0};
	sprintf(sql,"insert into tbl_message values(NULL,'%s','%s','%s',datetime('now'),'%d')",
			from,to,data,type);

	ret = sqlite3_exec(db,sql,NULL,NULL,&error);
	sqlite3_close(db);
	if (ret != SQLITE_OK)
    {
		perror("sqlite3_open error!");
		return -1;
	}
    else
    {
		return 0;
	}
}

char addrecord(char from[],char to[],char data[],int type)
{
	sqlite3* db;
	int ret = sqlite3_open("/home/liuyin/test/source/server/chatroom.db",&db);
	if (ret != SQLITE_OK)
    {
		sqlite3_close(db);
		perror("sqlite3 open error!");
		return -1;
	}
	char* error=NULL;
	char sql[100]={0};
	sprintf(sql,"insert into tbl_chatrecord values(NULL, '%s', '%s', '%s', datetime('now'), %d )", from, to, data, type);

	ret = sqlite3_exec(db, sql, NULL, NULL , &error);
	sqlite3_close(db);
	if (ret != SQLITE_OK)
    {
        printf("%s\n", error);
		perror("sqlite3_open error!");
		return -1;
	}
    else
    {
		return 0;
	}
}

char* getrecord(char from[],int type)
{
	sqlite3* db;
	int ret = sqlite3_open("/home/liuyin/test/source/server/chatroom.db",&db);
	if (ret != SQLITE_OK)
    {
		sqlite3_close(db);
		perror("sqlite3 open error!");
		return -1;
	}
	char* error=NULL;
	char sql[100]={0};
	sprintf(sql,"select * from tbl_chatrecord where fromwho='%s' or towho='%s'",from,from);
	int row,col;
	char** result;

	ret = sqlite3_get_table(db,sql,&result,&row,&col,&error);

	if (ret != SQLITE_OK)
    {
		sqlite3_free_table(result);
	    sqlite3_close(db);
		printf("%s\n", error);
		perror("sqlite3_open error!");
		return NULL;
	}
    else
    {
		printf( "查到%d条记录\n", row );
		printf("row=%d,col=%d\n",row,col);
        static char* record[1000];
		int i,j;
		for (i = 0; i <= row; i++)
        {
			for (j = 0; j < col; j++)
            {
				//printf("%s\t",*(result+(col*i+j)));
				strcat(record,*(result+(col*i+j)));
				strcat(record,"\t");
			}
			strcat(record,"\n");
		}
        sqlite3_free_table(result);
        sqlite3_close(db);
		return record;
	}
}

6、userdao.h

#ifndef USERDAO_H_
#define USERDAO_H_
/*
 * return
 * 0:success
 * -1:failure
 */

char login(char sname[],char passwd[]);
char login1(char id[],char passwd[]);

/*
 * return
 * 0:success
 * -1:failure
 */
char reg(char sname[],char passwd[]);

char* sid(char sname[]);

char* getuname(char id[]);

char addrecord(char from[],char to[],char data[],int type);

char* getrecord(char from[],int type);

char* forbidden(char sname[]);

char* forbidden1(char sname[]);

char* forb(char sname[]);

char* emoji(char from[],char to[],char data[]);

#endif /* USERDAO_H_ */

7、userdao.c

#include "userdao.h"
#include <sqlite3.h>
#include <string.h>
/*
 * return
 * 0:success
 * -1:failure
 */
char* forb(char sname[])
{
	sqlite3* db;
	int ret = sqlite3_open("/home/liuyin/test/source/server/chatroom.db",&db);
	if (ret != SQLITE_OK)
    {
		perror("sqlite3 open error!");
		exit(1);
	}
	char* error;
	char sql[100]={0};
	int row,col;
	char** result;
	sprintf(sql,"select state from tbl_user where sname='%s'",sname);
	ret = sqlite3_get_table(db,sql,&result,&row,&col,&error);
	sqlite3_close(db);
	if (ret != SQLITE_OK)
    {
		perror("sqlite3_open error!");
	}
	static char state[100];
	strcpy(state,result[row]);
	//printf("%s\n",state);
	sqlite3_free_table(result);
	sqlite3_close(db);
	return state;
}

char* forbidden(char sname[])
{
	sqlite3* db;
	int ret = sqlite3_open("/home/liuyin/test/source/server/chatroom.db",&db);
	if (ret!=SQLITE_OK)
    {
		perror("sqlite3 open error!");
		exit(1);
	}
	char* error;
	char sql[100]={0};
	int row,col;
	char** result;
	sprintf(sql,"update tbl_user set state  = 1 where sname='%s'",sname);
	ret = sqlite3_get_table(db,sql,&result,&row,&col,&error);
	sqlite3_close(db);
	if (ret != SQLITE_OK)
    {
		perror("sqlite3_open error!");
		return -1;
	}
    else
    {
		return 0;
	}
}

char* forbidden1(char sname[])
{
	sqlite3* db;
	int ret = sqlite3_open("/home/liuyin/test/source/server/chatroom.db",&db);
	if (ret != SQLITE_OK)
    {
		perror("sqlite3 open error!");
		exit(1);
	}
	char* error;
	char sql[100]={0};
	int row,col;
	char** result;
	sprintf(sql,"update tbl_user set state  = 0 where sname='%s'",sname);
	ret = sqlite3_get_table(db,sql,&result,&row,&col,&error);
	sqlite3_close(db);
	if (ret != SQLITE_OK)
    {
		perror("sqlite3_open error!");
		return -1;
	}
    else
    {
		return 0;
	}
}

char* getuname(char id[])
{
	sqlite3* db;
	int ret = sqlite3_open("/home/liuyin/test/source/server/chatroom.db",&db);
	if (ret != SQLITE_OK)
    {
		perror("sqlite3 open error!");
		exit(1);
	}
	char* error=NULL;
	char sql[100]={0};
	int row,col;
	char** result;
	sprintf(sql,"select sname from tbl_user where id='%s'",id);
	ret = sqlite3_get_table(db,sql,&result,&row,&col,&error);
	if (ret != SQLITE_OK)
    {
		sqlite3_close(db);
		perror("sqlite3_open error!");
	}
	sqlite3_free_table(result);
	sqlite3_close(db);
	if (row > 0)
    {
		static char name[100]={0};
		strcpy(name,result[1]);
		return name;
	}
    else
    {
		printf("未查询到name!\n");
		return NULL;
	}
/*
		static char uname[100]={0};
		sqlite3_free_table(result);
		sqlite3_close(db);
		if(row>0){
			strcpy(uname,result[1]);
			return uname;
		}else{
			return NULL;
		}
*/
}

char* sid(char sname[])
{
	sqlite3* db;
	int ret = sqlite3_open("/home/liuyin/test/source/server/chatroom.db",&db);
	if (ret!=SQLITE_OK)
    {
		perror("sqlite3 open error!");
		exit(1);
	}
	char* error;
	char sql[100]={0};
	int row,col;
	char** result;
	sprintf(sql,"select id from tbl_user where sname='%s'",sname);
	ret = sqlite3_get_table(db,sql,&result,&row,&col,&error);
	if (ret != SQLITE_OK)
    {
		sqlite3_close(db);
		perror("sqlite3_open error!");
	}

	static char id[100];
	strcpy(id,result[row]);
	sqlite3_free_table(result);
	sqlite3_close(db);
	return id;
}

char login(char sname[],char passwd[])
{
	sqlite3* db;
	int ret = sqlite3_open("/home/liuyin/test/source/server/chatroom.db",&db);
	if (ret!=SQLITE_OK)
    {
		perror("sqlite3 open error!");
		exit(1);
	}

	char* error;
	char sql[100]={0};
	sprintf(sql,"select * from tbl_user where sname='%s' and passwd='%s'",sname,passwd);
	//查询
	printf("sql=%s\n",sql);
	int row,col;
	char** result;//字符串的指针
	ret = sqlite3_get_table(db,"select * from tbl_user",&result,&row,&col,&error);
	if (ret != SQLITE_OK)
    {
		sqlite3_free_table(result);
		sqlite3_close(db);
		perror("sqlite3_open error!");
		exit(1);
	}
	sqlite3_free_table(result);
	sqlite3_close(db);
	printf("row=%d\n",row);
	if(row > 0)
    {
		return 0;
	}
	return -1;
}

char login1(char id[],char passwd[])
{
	    sqlite3*db;
		int ret =sqlite3_open("/home/liuyin/test/source/server/chatroom.db",&db);
		if (ret!=SQLITE_OK)
        {
			perror("sqlite3 open error!");
			exit(1);
		}
		char*error=NULL;
		char sql[100]={0};
		sprintf(sql,"select*from tbl_user where id='%s' and passwd='%s'",id,passwd);
		int row,col;
		char** result;
		ret=sqlite3_get_table(db,sql,&result,&row,&col,&error);
		if (ret!=SQLITE_OK)
        {
			sqlite3_free_table(result);
			sqlite3_close(db);
			perror("sqlite3_open error!");
			exit(1);
		}
		sqlite3_free_table(result);
		sqlite3_close(db);
		if (row >= 1)
        {
			return 0;
		}
        else
        {
			return -1;
		}
}

/*
 * return
 * 0:success
 * -1:failure
 */
char reg(char sname[],char passwd[])
{
	sqlite3* db;
	int ret = sqlite3_open("/home/liuyin/test/source/server/chatroom.db",&db);
	if (ret != SQLITE_OK)
    {
		sqlite3_close(db);
		perror("sqlite3 open error!");
		return -1;
	}
	char* error;
	char sql[100]={0};
	sprintf(sql,"insert into tbl_user values(NULL,'%s','%s',datetime('now'),'0')",sname,passwd);

	ret=sqlite3_exec(db,sql,NULL,NULL,&error);
	sqlite3_close(db);
	if (ret != SQLITE_OK)
    {
		perror("sqlite3_open error!");
		return -1;
	}
    else
    {
		return 0;
	}
}

char* emoji(char from[],char to[],char data[])
{
	static char emoji[1000]={0};
	static char b[1000]={0};

	if (strcmp(data,":)")==0)
    {
		strcpy(emoji,"向大家做了一个笑脸");
		return emoji;
	}
	if (strcmp(data,"wel")==0)
    {
		strcpy(emoji,b);
		strcat(emoji,"大侠,欢迎来到咱们的聊天室!");
		return emoji;
	}
    else
    {
		return data;
	}
}

8、chat_s.c(main 函数)

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sqlite3.h>

#include "link.h"
#include "chatroom.h"
#include "userdao.h"

#define PORT 50000

LinkList list;

void* process1(void* arg)
{
	Msg msg;
	unsigned int c_sockfd = *(unsigned int*)arg;
	while (1)
    {
        //先发后收
        memset(&msg,0,sizeof(Msg));
        read(c_sockfd,&msg,sizeof(Msg));
        if (msg.type == 0)
        {
            break;
        }
        printf("Msg[from=%s,to=%s,data=%s,type=%d,id=%s]\n",
                msg.from,msg.to,msg.data,msg.type,msg.id);

        if (addMsg(msg.from,msg.to,msg.data,msg.type) == -1)
        {
            printf("addMsg error!\n");
        }
        int suid = atoi(msg.id);
        switch (msg.type)
        {
            case REG:
                if (reg(msg.from,msg.data) == 0)
                {
                    printf("%s\n",sid(msg.from));
                    strcpy(msg.id,sid(msg.from));
                    int a=atoi(sid(msg.from));
                    sprintf(msg.data,"register successfully\n 您的ID为:%d",a);
                }
                else
                {
                    strcpy(msg.data,"register fail!");
                }
                write(c_sockfd,&msg,sizeof(Msg));
            break;
            case LOGIN:
                if (login1(msg.id,msg.data) == 0 && suid != 1)
                {
                        strcpy(msg.from,getuname(msg.id));
                        printf("%s",getuname(msg.id));
                        addFirst(&list,msg.from,c_sockfd);
                        strcpy(msg.data,"login successfully!");
                }
                else if (login1(msg.id,msg.data) == 0 && suid == 1)
                {
                    strcpy(msg.from,getuname(msg.id));
                    printf("%s",getuname(msg.id));
                    addFirst(&list,msg.from,c_sockfd);
                    strcpy(msg.data,"欢迎管理员,您拥有管理员权限!");
                }
                else
                {
                    strcpy(msg.data,"login fail!");
                }
                write(c_sockfd,&msg,sizeof(Msg));
            break;
            case USERLIST:
                strcpy(msg.from,getuname(msg.id));
                if (get(&list,msg.from) == NULL)
                {
                    strcpy(msg.data,"你已被踢出聊天室!");
                    write(c_sockfd,&msg,sizeof(Msg));
                    break;
                }
                else
                {
                    memset(msg.data,0,sizeof(msg.data));
                    userlist(&list,msg.data);
                    write(c_sockfd,&msg,sizeof(Msg));
                }
            break;
            case SENDMSG:
            {
                strcpy(msg.from,getuname(msg.id));
                char state=atoi(forb(msg.from));
                char data1[100];
                strcpy(data1,msg.data);
                if (addrecord(msg.from, msg.to, msg.data, msg.type) == -1)
                {
                    printf("addrecord error!\n");
                }
                if (get(&list,msg.from) == NULL)
                {
                    strcpy(msg.data,"你已被踢出聊天室!");
                    write(c_sockfd,&msg,sizeof(Msg));
                    break;
                }
                else if (state == 1)
                {
                    strcpy(msg.data,"你已被禁言!");
                    write(c_sockfd,&msg,sizeof(Msg));
                    break;
                }
                else
                {
                    Node* ptr = get(&list,msg.to);
                    if (ptr == NULL)
                    {
                        strcpy(msg.data,"user not exit!");
                        write(c_sockfd,&msg,sizeof(Msg));//谁给我发,我就给谁发
                    }
                    else
                    {
                        unsigned int sockfd = ptr->sockfd;
                        strcpy(msg.data,emoji(msg.from,msg.to,data1));
                        write(sockfd,&msg,sizeof(Msg));//找到接受着,就发给他
                    }
                }
                break;
            }
            case SENDFILE:
            {
                strcpy(msg.from,getuname(msg.id));
                if (addrecord(msg.from, msg.to, msg.data, msg.type) == -1)
                {
                    printf("addrecord error!\n");
                }
                if (get(&list,msg.from) == NULL)
                {
                    strcpy(msg.data,"你已被踢出聊天室!");
                    write(c_sockfd,&msg,sizeof(Msg));
                    break;
                }
                else
                {
                    Node* ptr =  get(&list, msg.to);
                    if (ptr == NULL)
                    {
                        strcpy(msg.data,"user not exist!");
                        write(c_sockfd, &msg, sizeof(Msg));//谁给我发,我就发给谁
                    }
                    else
                    {
                        char filepath[100];
                        unsigned int sockfd = ptr->sockfd;
                        memset(filepath,0,sizeof(filepath));
                        sprintf(filepath,"/home/ben/c.d/%s",msg.data);
                        printf("filepath=%s\n",filepath);
                        printf("%s\n", msg.data);
                        int fd = open(filepath,O_RDONLY);
                        if (fd == -1)
                        {
                            strcpy(msg.data,"File Not Found!");
                            write(c_sockfd, &msg, sizeof(Msg));
                        }
                        int len;
                        while (1)
                        {
                            len = read(fd,msg.data,1000);
                            write(sockfd, &msg,sizeof(Msg));
                            if (len < 1000)
                            {
                                break;
                            }
                        }
                    }
                }
                break;
            }
            case BROADCAST:
            {
                strcpy(msg.from,getuname(msg.id));
                if (addrecord(msg.from, msg.to, msg.data, msg.type) == -1)
                {
                    printf("addrecord error!\n");
                }
                if (get(&list,msg.from) == NULL)
                {
                    strcpy(msg.data,"你已被踢出聊天室!");
                    write(c_sockfd,&msg,sizeof(Msg));
                    break;
                }
                else
                {
                    int len = list.len;
                    Node* ptr = list.head;
                    while (len--)
                    {
                        if (strcmp(msg.from,ptr->uname) != 0)
                        {
                            Node* tp=get(&list,ptr->uname);
                            write(tp->sockfd,&msg,sizeof(Msg));
                        }
                        ptr = ptr->next;
                    }
                }
                break;
            }
            case BROADCASTFILE:
            {
                strcpy(msg.from,getuname(msg.id));
                if (addrecord(msg.from, msg.to, msg.data, msg.type) == -1)
                {
                    printf("addrecord error!\n");
                }
                if (get(&list,msg.from) == NULL)
                {
                    strcpy(msg.data,"你已被踢出聊天室!");
                    write(c_sockfd,&msg,sizeof(Msg));
                    break;
                }
                else
                {
                    char filepath[100];
                    memset(filepath,0,sizeof(filepath));
                    sprintf(filepath,"/home/ben/c.d/%s",msg.data);
                    printf("filepath=%s\n",filepath);
                    printf("%s\n", msg.data);

                    int len=list.len;
                    Node*ptr=list.head;
                    while (len--)
                    {
                        if (strcmp(msg.from,ptr->uname) != 0)
                        {
                            Node* tp = get(&list, ptr->uname);
                            int fd = open(filepath,O_RDONLY);
                            if (fd == -1)
                            {
                                strcpy(msg.data,"File Not Found!");
                                write(c_sockfd, &msg, sizeof(Msg));
                            }
                            int leng;
                            while (1)
                            {
                                leng = read(fd,msg.data,1000);
                                write(tp->sockfd, &msg,sizeof(Msg));
                                if (leng < 1000)
                                {
                                    break;
                                }
                            }
                        }
                        ptr = ptr->next;
                    }
                }
                break;
            }
            case KICK:
            {
                if (suid == 1)
                {
                    strcpy(msg.from,getuname(msg.id));
                    Node* ptr = get(&list,msg.to);
                    if (ptr == NULL)
                    {
                        strcpy(msg.data,"user not exist!");
                    }
                    else
                    {
                        del(&list,msg.to);
                        strcpy(msg.data,"踢出成功!");
                        //unsigned int sockfd = ptr->sockfd;
                        //write(sockfd,&msg,sizeof(Msg));
                    }
                }
                else
                {
                    strcpy(msg.data,"You do not have enough clearance!");
                }
                write(c_sockfd,&msg,sizeof(Msg));
                break;
            }
            case FORBIDDEN:
                strcpy(msg.from,getuname(msg.id));
                if (suid == 1)
                {
                    //strcpy(msg.from,getuname(msg.id));
                    Node* ptr = get(&list,msg.to);
                    if (ptr == NULL)
                    {
                        strcpy(msg.data,"user not exist!");
                    }
                    else
                    {
                        forbidden(msg.to);
                        strcpy(msg.data,"禁言成功!");
                    }
                }
                else
                {
                    strcpy(msg.data,"You do not have enough clearance!");
                }
                write(c_sockfd,&msg,sizeof(Msg));
                break;
            case LIFT:
                strcpy(msg.from,getuname(msg.id));
                if (suid == 1)
                {
                    //strcpy(msg.from,getuname(msg.id));
                    Node* ptr = get(&list,msg.to);
                    if (ptr == NULL)
                    {
                        strcpy(msg.data,"user not exist!");
                    }
                    else
                    {
                        forbidden1(msg.to);
                        strcpy(msg.data,"解禁成功!");
                    }
                }
                else
                {
                    strcpy(msg.data,"You do not have enough clearance!");
                }
                write(c_sockfd,&msg,sizeof(Msg));
                break;
            case LOGOUT:
                strcpy(msg.from,getuname(msg.id));
                if (del(&list,msg.from) == 0)
                {
                    strcpy(msg.data,"logout error!\n");
                }
                else
                {
                    strcpy(msg.data,"logout successfully\n");
                }
                break;
            case RECORD:
            {
                strcpy(msg.data,getrecord(msg.from,msg.type));
                write(c_sockfd, &msg, sizeof(Msg));
                break;
            }
            break;
        }
	}
	close(c_sockfd);
	return NULL;
}

int main()
{
	struct sockaddr_in s_addr,c_addr;

	unsigned int addrlen=sizeof(struct sockaddr_in);

	int c_sockfd,s_sockfd;
	s_sockfd=socket(AF_INET,SOCK_STREAM,0);
	if (s_sockfd == -1)
    {
	    perror("sockdt error!");
	    exit(1);
	}
	memset(&s_addr,0,addrlen);
	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(PORT);
	s_addr.sin_addr.s_addr = inet_addr("192.168.226.128");

	int opt = 1;
	setsockopt(s_sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
	if (bind(s_sockfd,(struct sockaddr *)&s_addr,addrlen) == -1)
    {
	    perror("bind error!");
	    exit(1);
	}
	if (listen(s_sockfd,10) == -1)
    {
		perror("listen error!");
	    exit(1);
	}
	printf("start accepting!\n");//等待客户端链接

	memset(&c_addr,0,addrlen);

	while (1)
    {
		c_sockfd=accept(s_sockfd,(struct sockaddr *)&c_addr,&addrlen);//阻塞
	    if (c_sockfd == -1)
        {
	    	perror("accept error!");
	    	exit(1);
	    }
	    pthread_t ptid;
	    if (pthread_create(&ptid,NULL,process1,&c_sockfd) == -1)
        {
	    	perror("pthread_create error!");
	    	exit(1);
	    }
	}
	return 0;
}

9、Makefile(后加的)

OBJ = chat_s.o link.o messagedao.o userdao.o 

server:$(OBJ)
	gcc -o server $(OBJ) -lpthread

chat_s.o:chat_s.c link.h chatroom.h userdao.h
	gcc -c chat_s.c

link.o:link.c link.h 
	gcc -c link.c

messagedao.o:messagedao.c messagedao.h userdao.h
	gcc -c messagedao.c

userdao.o:userdao.c userdao.h 
	gcc -c userdao.c

.PHONY:clean
clean:
	rm server $(OBJ)

二、client端

client.c

#include "link.h"
#include "chatroom.h"
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>

#define PORT 50000

void* readMsg(void* arg)
{
    unsigned int s_sockfd = *(unsigned int*)arg;
    Msg msg;
    while (1)
    {
        memset(&msg,0,sizeof(Msg));
        read(s_sockfd,&msg,sizeof(Msg));
        if (strlen(msg.data) == 0)
        {
            sleep(1);
            continue;
        }
        printf("from:%s\n",msg.from);
        printf("data:%s\n",msg.data);
        usleep(1);
    }
}

void* sendMsg(void* arg)
{
    char uname[10];
    char id[100];
    Msg msg;
    unsigned int s_sockfd = *(unsigned int*)arg;
    int choice;
    while(1)
    {
        printf("1.注册 2.登录 3.查看用户列表 4.发送消息 5.发送文件 6.群发 7.群发文件 8.踢人 9.禁言 10.解禁 11.登出 12.查询聊天记录 0.退出\n");
        scanf(" %d",&choice);
        switch (choice)
        {
            case REG:
                msg.type = REG;
                printf("请输入用户名:");
                scanf(" %s",msg.from);
                memset(uname,0,sizeof(uname));
                strcpy(uname,msg.from);
                printf("请输入密码:"); 
                scanf(" %s",msg.data);
                write(s_sockfd,&msg,sizeof(Msg));
                break;
            case LOGIN:
                msg.type = LOGIN;
                printf("请输入用户id:");
                scanf(" %s",msg.id);
                memset(id,0,sizeof(id));
                strcpy(id,msg.id);
                printf("请输入密码:");
                scanf(" %s",msg.data);
                printf("%s\n",msg.id);
                write(s_sockfd,&msg,sizeof(Msg));
                break;
            case USERLIST:
                msg.type = USERLIST;
                write(s_sockfd,&msg,sizeof(Msg));
                break;
            case SENDMSG:{
                msg.type = SENDMSG;
                printf("请输入要发送的用户:\n");
                scanf(" %s",msg.to);
                //write(s_sockfd, &msg, sizeof(Msg));
                printf("请输入内容:\n");
                scanf(" %s",msg.data);
                //printf("from:%s\n",msg.from);
                write(s_sockfd, &msg, sizeof(Msg));
                usleep(1);
                printf("to:%s\n",msg.to);
                break;
                }
            case SENDFILE:
                msg.type = SENDFILE;
                printf("请输入要发送的用户:\n");
                scanf(" %s",msg.to);
                printf("请输入文件名:\n",msg.data);
                scanf(" %s",msg.data);
                write(s_sockfd, &msg, sizeof(Msg));
                break;
            case BROADCAST:
                msg.type = BROADCAST;
                printf("Enter your message:\n");
                scanf(" %s",msg.data);
                write(s_sockfd,&msg,sizeof(Msg));
                break;
            case BROADCASTFILE:
                msg.type = BROADCASTFILE;
                printf("请输入文件名:\n",msg.data);
                scanf(" %s",msg.data);
                write(s_sockfd, &msg, sizeof(Msg));
                break;
            case KICK:
                msg.type = KICK;
                printf("请输入要踢出的用户名:\n");
                scanf(" %s",msg.to);
                write(s_sockfd, &msg, sizeof(Msg));
                break;
            case FORBIDDEN:
                msg.type = FORBIDDEN;
                printf("请输入要禁言的用户名:\n");
                scanf(" %s",msg.to);
                write(s_sockfd, &msg, sizeof(Msg));
                break;
            case LIFT:
                msg.type = LIFT;
                printf("请输入要解禁的用户名:\n");
                scanf(" %s",msg.to);
                write(s_sockfd, &msg, sizeof(Msg));
                break;
            case LOGOUT:
                msg.type = LOGOUT;
                strcpy(msg.id,id);
                write(s_sockfd,&msg,sizeof(Msg));
                usleep(1);
                //close(s_sockfd);
                break;
            case RECORD:
                msg.type = RECORD;
                write(s_sockfd, &msg, sizeof(Msg));
                break;
            case 0:
                exit(0);
                break;
        }
    }
}
int main()
{
    struct sockaddr_in s_addr;

    unsigned int addrlen=sizeof(struct sockaddr_in);

    int s_sockfd;
    s_sockfd=socket(AF_INET,SOCK_STREAM,0);
    if (s_sockfd == -1)
    {
        perror("sockdt error!");
        exit(1);
    }
    memset(&s_addr,0,addrlen);
    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(PORT);
    s_addr.sin_addr.s_addr = inet_addr("192.168.226.128");

    if (connect(s_sockfd,(struct sockaddr *)&s_addr,addrlen) == -1)
    {
        perror("bind error!");
        exit(1);
    }
    pthread_t pid1,pid2;//创建多线程
    if (pthread_create(&pid1,NULL,readMsg,&s_sockfd) == -1)
    {
        perror("pthread1_create error!");
        exit(1);
    }
    if (pthread_create(&pid2,NULL,sendMsg,&s_sockfd) == -1)
    {
        perror("pthread1_create error!");
    }

    pthread_join(pid1,NULL);
    pthread_join(pid2,NULL);

    return 0;
}

三、总结

以上就是整个简易聊天室了。因为是很久之前写的了,电脑重装过几次,只留下了一些笔记,编译的环境都没了,主要是sqlite3需要下载,现在又很少使用(几乎不用)sqlite3,所以也没有重新编译过,就当留个纪念吧。

创作不易,点个赞吧。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值