网络编程项目:linux下基于C/S架构的聊天室

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情

一、项目要求:

1. 采用 Client/Server 架构 

2. Client A 登陆聊天服务器前,需要注册自己的 ID 和密码 
3. 注册成功后,Client A 就可以通过自己的 ID 和密码登陆聊天服务器 
4. 多个 Client X 可以同时登陆聊天服务器之后,与其他用户进行通讯聊天 
5. Client A 成功登陆后可以查看当前聊天室内其他在线用户 Client x 
6. Client A 可以选择发消息给某个特定的 Client X,即”悄悄话”功能 
7. Client A 可以选择发消息全部的在线用户,即”群发消息”功能 
8. Client A 在退出时需要保存聊天记录 

9. Server 端维护一个所有登陆用户的聊天会的记录文件,以便备查 

10.可以进行文件传输

二、附加功能:

1. Server 可以内建一个特殊权限的账号 root,即超级管理员,用于管理聊天室 
2. Admin 可以将某个 Client X “提出聊天室” 
3. Admin 可以将某个 Client X ”设为只能旁听,不能发言,即禁言功能


三、项目所需相关知识点:网络编程(C/S模型的架构),文件I/O编程(将用户信息和聊天记录保存在数据库文件中,文件传输),多进程或多线程编程(一个服务器可以连接多个客户端)


四、项目使用(测试)说明:将client.c, client.c和server.c分别置于不同目录下,编译命令:gcc  client.c  -o  client   -lpthread  -lsqlite3

运行命令:./client     (server.c同样编译运行)


五、项目代码

服务器:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sqlite3.h>

#include <sys/stat.h>
#include <fcntl.h>

#define SIZE 20
#define PORT  9999
#define TRUE   1
#define FALSE -1

struct Usr
{
	char name[SIZE];
	int socket;
	int flag;//用来判断该用户是否被禁言,没有被禁设为0,被禁设为1
};

struct Msg
{
	struct Usr usr[SIZE];
	char msg[1024];
	char buf[1024];
	char name[SIZE];
	char fromname[SIZE];
	char toname[SIZE];
	char password[SIZE];
	int cmd;
	int filesize;
	int flag;    //用来判断用户权限   0代表普通用户,1代表超级用户
};

struct Usr usr[SIZE];
int count;

pthread_mutex_t mutex; //互斥锁,用来避免两个客户端同时访问全局变量

//查看在线用户
void see_online(int client_socket, struct Msg *msg)
{
	int i;
	for(i=0; i<20; i++)
	{
		msg->usr[i] = usr[i];
	}
	
	write(client_socket, msg, sizeof(struct Msg));
}

//保存一条聊天记录
void insert_record(struct Msg *msg)
{
	sqlite3 * database;
	int ret = sqlite3_open("allrecord.db", &database);
	if (ret != SQLITE_OK)
	{
		printf ("打开数据库失败\n");
		return ;
	}
	
	//获取系统当前时间
	time_t timep;  
    char s[30];   
    time(&timep);  
    strcpy(s,ctime(&timep));
	int count = strlen(s);
	s[count-1] = '\0';
	
	char *errmsg = NULL;
	char *sql = "create table if not exists allrecord(time TEXT,fromname TEXT,toname TEXT,word TEXT)";
	ret = sqlite3_exec(database, sql, NULL, NULL, &errmsg);
	if (ret != SQLITE_OK)
	{
		printf ("聊天记录表创建失败:%s\n", errmsg);
		return;
	}
	
	char buf[100];
	sprintf(buf, "insert into allrecord values('%s','%s','%s','%s')",s,msg->fromname, msg->toname,msg->msg);
	ret = sqlite3_exec(database, buf, NULL, NULL, &errmsg);
	if (ret != SQLITE_OK)
	{
		printf ("添加聊天记录失败:%s\n", errmsg);
		return ;
	}
	
	sqlite3_close(database);
	return ;
}

//群聊
void chat_group(int client_socket, struct Msg *msg)
{
	int i = 0;
	for (i = 0; i < SIZE; i++)
	{
		if (usr[i].socket != 0 && strcmp(msg->fromname, usr[i].name) == 0)
		{
			break;
		}
	}
	if(usr[i].flag == 0)     //判断该用户有没有被禁言
	{
		printf ("%s 发一次群消息\n", msg->fromname);
		insert_record(msg);
		
		for (i = 0; i < SIZE; i++)
		{
			if (usr[i].socket != 0 && strcmp(msg->fromname, usr[i].name) != 0)
			{
				write (usr[i].socket, msg, sizeof(struct Msg));	
			}
		}
	}
	else
	{
		msg->cmd = 1003;
		write (client_socket, msg, sizeof(struct Msg));
	}
	
}

//私聊
void chat_private(int client_socket, struct Msg *msg)
{
	int i;
	for (i = 0; i < SIZE; i++)
	{
		if (usr[i].socket != 0 && strcmp(msg->fromname, usr[i].name) == 0)
		{
			break;
		}
	}
	if(usr[i].flag == 0)
	{
		printf("%s给%s发了一条消息\n", msg->fromname, msg->toname);
		insert_record(msg);
		
		for (i = 0; i < SIZE; i++)
		{
			if (usr[i].socket != 0 && strcmp(usr[i].name, msg->toname)==0)
			{
				write (usr[i].socket, msg, sizeof(struct Msg));	
				break;
			}
		}
	}
	else
	{
		msg->cmd = 1003;
		write (client_socket, msg, sizeof(struct Msg));
	}
}

//获取文件大小
int file_size(char* filename)  
{  
    struct stat statbuf;  
    stat(filename,&statbuf);  
    int size=statbuf.st_size;  
  
    return size;  
}

//上传文件
void send_file(int client_socket, struct Msg *msg)
{
	printf("用户%s在聊天室内上传了一个文件%s\n",msg->fromname,msg->msg);
	
	int i;
	for (i = 0; i < SIZE; i++)
	{
		if (usr[i].socket != 0 && strcmp(usr[i].name, msg->fromname) != 0)
		{
			write (usr[i].socket, msg, sizeof(struct Msg));	
			break;
		}
	}
	
	int fd = open(msg->msg, O_RDWR | O_CREAT, 0777);
	if(fd == -1)
	{
		perror("open");
		printf("文件传输失败\n");
	}
	
	int size = msg->filesize;
	char buf[65535];
	memset(buf, 0, 65535);
	
	int ret = read(client_socket, buf, size);
	if(ret == -1)
	{
		perror("read");
		return;
	}	
	write(fd, buf, ret);
	close(fd);
}

//从用户数据库删除一个用户
void del_fromsql(struct Msg *msg)
{
	sqlite3 * database;
	int ret = sqlite3_open("usr.db", &database);
	if (ret != SQLITE_OK)
	{
		printf ("打开数据库失败\n");
		return;
	}
	
	char *errmsg = NULL;
	char buf[100];
	sprintf(buf, "delete from usr where name = '%s'", msg->name);
	ret = sqlite3_exec(database, buf, NULL, NULL, &errmsg);
	if (ret != SQLITE_OK)
	{
		printf ("删除用户失败:%s\n", errmsg);
		return;
	}
	
	sqlite3_close(database);
	return;
}

//注销用户
void logout(int client_socket,struct Msg *msg)
{
	int i,j;
	for(i=0; i<count; i++)
	{
		if(strcmp(msg->name, usr[i].name) == 0)
			break;
	}
	for(j=i; j<count; j++)
	{
		usr[j] = usr[j+1];
	}
	count--;
	printf("正在注销用户%s\n",msg->name);
	del_fromsql(msg);
	
	write(client_socket, msg, sizeof(struct Msg));
	return;
	
}

//用户下线
void off_line(int client_socket,struct Msg *msg)
{
	pthread_mutex_lock(&mutex);    // 抢锁
	
	printf("用户%s下线\n",msg->name);
	int i,j;
	for(i=0; i<count; i++)
	{
		if(strcmp(msg->name, usr[i].name) == 0)
			break;
	}
	for(j=i; j<count; j++)
	{
		usr[j] = usr[j+1];
	}
	count--;
	
	pthread_mutex_unlock(&mutex);  // 解锁
	write(client_socket, msg, sizeof(struct Msg));
	
	return;
}

//用户下载文件
void download_file(int client_socket,struct Msg *msg)
{
	printf("用户%s下载了文件%s\n", msg->name, msg->msg);
	int size = file_size(msg->msg);
	msg->filesize = size;
	write(client_socket, msg, sizeof(struct Msg));
	
	usleep(100000);
	
	int fd = open(msg->msg, O_RDONLY, 0777);
	if(fd == -1)
	{
		perror("open");
		printf("文件下载失败\n");
	}
	
	char buf[65535];
	memset(buf, 0, 65535);

	int ret = read(fd, buf, size);
	if(ret == -1)
	{
		perror("read");
		return;
	}
    	
	write(client_socket, buf, ret);
基于C/S架构的网络聊天室 服务器端 #include #include #include #include #include #include #include #include #include #include #include #include "LinkList.h" #define PORT 9999 typedef struct _msg { int cmd; int flag; 阅读详情

相关推荐

聊天室(c/s架构

项目要求: (1)采用 Client/Server 架构 。  (2) Client A 登陆聊天服务器前,需要注册自己的 ID 和密码。  (3)注册成功后,ClientA 就可以通过自己的 ID 和密码登陆聊天服务器 。  (4). 多个 Client X 可以同时登陆聊天服务器之后,与其他用户进行通讯聊天。  (5).Client A 成功登陆后可以查看当前聊天室内其他在线用户 C

ZH0314的博客 2789

基于C/S架构聊天系统的实现

基于C/S架构聊天系统的实现, 运用NIO机制 Socket通信,通过多线程IO操作等技术实现好友添加,删除好友,好友聊天,文件互传功能,可用于java语言的练习与提高

基于C/S的聊天系统的设计与实现

基于C/S的聊天系统的设计与实现

m0_60891993的博客 745

基于SOCKET的C/S结构聊天室

基于java的socket网络聊天室,可以实现用户在线列表显示、用户下线提示、群聊和私聊功能。本人课程设计做的,可能会有少许bug。

多人聊天室(带私聊功能)Linux网络编程基础

Linux网络编程是我们这学期学习嵌入式的重要内容:不仅仅是期末作业,更是对linux网络编程的巩固。接下来我会将全部内容分享出来哈哈ψ(`∇´)ψ提示:完成得比较随意,不够严谨,仅供参考,大家都能做得更好!太好咯,又做完一个作业 哈哈哈O(∩_∩)O。

qq_59147881的博客 8211

linux网络编程——聊天室总结

说在前面 暑假留校的主要任务是学习linux下的c语言编程,之前写了my_ls, my_shell这两个可以说是练手的小项目,而最后的项目聊天室也是花了自己快两周的时间,说实话第一次写这种(对自己而言)大项目,最深刻的体会就是整体的架构很重要,很重要,很重要… 项目概述 Linux 环境下的简易聊天室,采用C/S模型,实现多客户端之间的稳定数据传输。 功能 登陆注册账号,登陆时密码不会显 好友管...

qq_43646576的博客 4584

linux下自创网络编程聊天室(3)

总体设计 本聊天室系统采用了c/s形式。服务器主要是处理客户输入信息。首先要存储客户的个人资料,相当于注册。再有,在客户的聊天信息时,也要记录下客户的聊天记录,已备查看聊天记录所用。当然,服务器还有自己的动态数据处理。客户状态分为链接客户和非连接客户,我采用结构体存储链接客户信息,以链表来记录链接客户。而链接客户又分为登陆客户和未登陆客户,这就通过修改链表上客户的名字。当客户一链接客户服务端

h674174380的博客 4834

linux下自创网络编程聊天室(2)

总体设计 本聊天室系统采用了c/s形式。服务器主要是处理客户输入信息。首先要存储客户的个人资料,相当于注册。再有,在客户的聊天信息时,也要记录下客户的聊天记录,已备查看聊天记录所用。当然,服务器还有自己的动态数据处理。客户状态分为链接客户和非连接客户,我采用结构体存储链接客户信息,以链表来记录链接客户。而链接客户又分为登陆客户和未登陆客户,这就通过修改链表上客户的名字。当客户一链接客户服务端时,

h674174380的博客 8913

Linux环境,C语言实现聊天室

写在前面:这个小项目运用了socket技术,可以先学习一下socket的基本函数和用法再看代码~ socket详解 网络聊天室业务逻辑: 1、客户端注册名字 2、告诉所有的在线的客户端,XXX进入聊天室。 3、新建一个线程为该客户端服务,随时接收客户端发送来的内容。 4、当收到一个客户端的消息时,向每个客户端都转发一份(群聊)。 5、同时在线人数最多50人。 注意:任何客户端都应该可以随时进入退出。 客户端 #include <stdio.h> #include <stdlib.h&g

liuxinyullll的博客 3607

基于Java的c/s架构聊天室

自己学java做的c/s架构聊天室,用户注册挂的数据库数据库的驱动、用户名和密码什么的在根目录的db.properties里面配置,eclipse的项目包,可以直接导入,做工拙劣,如有不足之处还望指点。

Linux环境下C语言聊天室项目:简易局域网聊天工具

Linux环境下C语言聊天室项目:简易局域网聊天工具 【下载地址】Linux环境下C语言聊天室项目 这是一个基于Linux平台的C语言聊天室项目,采用C/S架构,实现了局域网内的实时通信功能。通过Berkeley套接口编程,客户端与服务器端可以高效地进行数据传输,所有聊天内容会在终端实时显示。项目结构清晰,功能简洁实用,...

gitblog_06796的博客 834

Linux环境下——C语言聊天室项目

Linux环境下——C语言聊天室项目 【下载地址】Linux环境下C语言聊天室项目 这是一个基于Linux平台的C语言聊天室项目,采用C/S架构,实现了局域网内的实时通信功能。通过Berkeley套接口编程,客户端与服务器端可以高效地进行数据传输,所有聊天内容会在终端实时显示。项目结构清晰,功能简洁实用,非常适合初学者学...

gitblog_06746的博客 925

linux下自创网络编程聊天室(1)

在线聊天室 在线聊天室,通过网络建立的虚拟聊天室,分为文字聊天室,视频聊天室。 网络聊天室是在一个网站中,供许多人通过文字与符号进行实时(您输入的内容马上就能被别人看见)交谈、聊天的场所,它是一个向整个因特网开放的地方。 E时代 “E时代”的到来,给人们提供了各种便利。然而,其中受非议最多、名声最差的莫过于网络聊天了。人们从新闻媒体中听说的、与网络聊天有关的事件,十有八九与诈骗、抢劫、杀人等社

h674174380的博客 2414

Linux网络编程项目——C语言基于TCP通信协议实现的网络聊天室

目前,网络已经成为人们日常生活中不可缺少的部分,网络聊天也正在一步步的取代短信的使用。本文主要介绍如何利用 网络编程 + 多线程编程 实现一个简易的网络聊天室

2301_80350206的博客 3333

【亲测免费】 推荐开源项目:HLW聊天室——Linux C网络编程的艺术之作

推荐开源项目:HLW聊天室——Linux C网络编程的艺术之作 1、项目介绍 HLW聊天室是一款由Linux C语言编写的多功能聊天工具,它采用字符界面,提供了用户注册登录、添加好友、私聊、群聊、文件传输等一系列在线交流功能。这款开源软件不仅展示了C语言在网络编程中的强大之处,还揭示了如何在没有图形用户界面的情况下实现高效、流畅的通信体验。 2、项目技术分析 HLW聊天室基于经典的C/S(客户端/...

gitblog_00073的博客 3484

Linux c网络编程聊天室项目

涉及内容 C/s框架,多线程,进程,TCP/UDP双协议,c库文件,sqlite3,线程池,码量6000+ 主要实现功能:注册,登录,忘记、修改、查找密码,信息群私收发,文件群私收发,常用语问候语群私收发,实时查看在线用户等等。 要实现这些功能,一定要弄清自己的思路,登录前后登录后用户的功能的实现。 我就直接上代码了: 服务器(部分代码): 客户端(全部代码) /**********************************************************************

m0_60375038的博客 2239

C++网络编程实战:从零构建C/S架构多人聊天室

网络编程是构建分布式系统的核心技术,其核心在于实现不同主机间的进程通信。在众多网络模型中,客户端/服务器(C/S)架构因其逻辑清晰、易于管理而成为经典范式,尤其适用于需要集中控制和状态维护的应用场景。通过Socket API,程序可以建立可靠的端到端连接,其中TCP协议凭借其面向连接、可靠传输和有序交付的特性,成为需要保证数据完整性的应用(如即时通讯、文件传输)的首选。结合多线程技术,服务器能够高效处理并发连接,利用线程池管理资源,避免频繁创建销毁线程的开销,从而提升系统吞吐量和响应能力。这种技术组合在构建

weixin_34211761的博客 292

Linux C/S网络编程实训:单机版聊天室项目全解析

在计算机科学领域,网络编程是构建分布式应用的基础,其核心在于理解进程间通信(IPC)与网络协议。Socket编程作为网络通信的基石,通过TCP/IP协议栈实现可靠的数据传输。其技术价值在于能够构建稳定、高效的客户端/服务器(C/S)模型应用,广泛应用于即时通讯、在线游戏和物联网等场景。本文聚焦于一个经典的Linux C/S网络编程实训项目——单机版聊天室,深入剖析其多线程并发模型与TCP粘包处理等关键技术。通过解析**多线程**架构下的资源共享与同步机制,以及**消息头+消息体**协议设计如何解决TCP流式

weixin_31528001的博客 331
上一篇: C++面向对象的学习:写一个数组类
baymin_dly
博客等级 码龄9年 26粉丝 31原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值