基于C语言的网络编程的项目

首先,这个项目仅仅只是一个模板,需要大家进行后续开发,我把此模板进行开源

我这个项目运用到的技术有TCP通信协议、IO多路复用、sqlite3数据库、循环服务器等,在进行编写之前,需要大家进行了解(当然,你们还可以根据自己的需求,把项目改写成多线程或者多进程进行编写)

  1. 在开始项目之前,需要大家对TCP通信进行大概的了解,嗯,TCP通信的话就像是在打电话,流程图如下:
    在这里插入图片描述
  2. 也就是需要完成客户端和服务器端的连接操作,成功之后,方可进行项目内容的操作。

client.c文件

还可以将项目改写成嵌套makefile的形式,这里我是以子函数进行编写,没有拆分
client.c文件   这里的头文件我进行省略,因为太多,可以man一下进行添加
int tcp_connect(const char * ip,int port)
{

	//1.创建套接子文件 socket
	int tcp_socket = socket(AF_INET,SOCK_STREAM,0);  //TCP
	if(tcp_socket < 0)
	{
		perror("创建套接子失败!\n");
	}
	printf("创建套接子成功!\n");

	//2.创建对方的IP和端口号	
	struct sockaddr_in server;

	server.sin_family = AF_INET;
	server.sin_port = htons(port); //主机到网络字节序
	server.sin_addr.s_addr = inet_addr(ip);//主机到网络字节序 

	//3.请求连接套接子
	if(connect(tcp_socket,(struct sockaddr *)&server,sizeof(server))<0)
	{
		perror("连接套接字失败!\n");	
		return -1;
	}
	printf("连接套接字成功!\n");
	return tcp_socket;
}
void tcp_com(int tcp_socket)
{
//tcp通信 这里的通信可以大家自由发挥
}
int main(int argc, const char *argv[])
{
	if(argc<3)
	{
		printf("input appname ip port\n");
		return -1;
	}

	//1.连接Tcp服务器
	int tcp_socket=tcp_connect(argv[1],atoi(argv[2]));
	//2.tcp通信 这里的通信可以大家自由发挥
	tcp_com(tcp_socket);
	//3.关闭套接子
	close(tcp_socket);

	return 0;
}

server.c文件

这里是服务器端
server.c文件
int tcp_server(const char * ip,int port)
{
	//1.创建tcp_socket对象
	int tcp_socket=0;
	tcp_socket=socket(AF_INET,SOCK_STREAM,0);
	if(tcp_socket<0)
	{
		perror("socket error");
		return -1;
	}
	printf("socket ok\n");

	//2.绑定自己的IP地址和端口号
	struct sockaddr_in myaddr;
	myaddr.sin_family=AF_INET;//协议
	myaddr.sin_addr.s_addr=inet_addr(ip);//INADDR_ANY 自动获取一个什么我们就用什么
	myaddr.sin_port=htons(port);
	if(bind(tcp_socket,(struct sockaddr *)&myaddr,sizeof(myaddr))<0)
	{
		perror("bind error");
		return -1;
	}
	printf("bind ok\n");
	//3.监听是否有人连接
	if(listen(tcp_socket,5)<0)
	{
		perror("listen error");
		return -1;
	}
	printf("listen ok\n");
	return tcp_socket;

}
int tcp_com(int newfd)
{
	//这里也是大家自由发挥的地方,切记,连接成功,需要跟client.c进行一一对应。
}
//运用并发服务器的IO多路复用
int main(int argc, const char *argv[])
{
	if(argc<3)
	{
		printf("input appname ip port\n");
		return -1;
	}

	//1.获得监听好的socket对象
	int tcp_socket=tcp_server(argv[1],atoi(argv[2]));
	//2.接受连接生成新的socket对象
	int newfd=0;
	//newfd=accept(tcp_socket,NULL,NULL); //若不关心对方的IP地址和port
	//参数2,3,设置为NULL				//

	//关心一下端的IP地址和端口号 
	struct sockaddr_in client;

	//1.定义两个文件描述符
	fd_set rdfs;
	fd_set temp;
	//清空两个文件的集合
	FD_ZERO(&rdfs);
	FD_ZERO(&temp);
	//将监听的socket对象加入到文件描述符集合里
	FD_SET(tcp_socket,&rdfs);
	while(1)
	{
		temp = rdfs;//监控的是temp
		struct timeval tv;
		tv.tv_sec = 5;
		tv.tv_usec = 0;
		int reval = select(FD_SETSIZE,&temp,NULL,NULL,&tv);
		if(reval <0)
		{
			perror("select error");
			return -1;
		}
		else if(reval ==0)
		{
			printf("select timeout\n"); //超时
		}
		else if(reval > 0)
		{
			int i=0;
			for(i=0;i<FD_SETSIZE;i++)
			{
				//判断那个文件描述符有数据
				if(FD_ISSET(i,&temp))
				{
					if(i == tcp_socket)
					{//若是监听socket,表示客户端来连接
					memset(&client,'\0',sizeof(client));
					int len=sizeof(client);
					newfd=accept(tcp_socket,(struct sockaddr *)&client,&len);
					if(newfd<0)
					{
						perror("accept error");
						return -1;
					}
					printf("client ip=%s   port=%d accept ok\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
					FD_SET(newfd,&rdfs);//将新生成的socket加入集合中
					}
					else
					{
						//通过套接字,表示客户端有数据可读
						//3.TCP通信	
						int n = tcp_com(i);
						if(n<0)
						{
							printf("%d断了\n",i);
							FD_CLR(i,&rdfs);//将文件描述符从集合中删除
							//4.关闭socket对象
							close(i);
						}
					}
				}
			}
		}
	}
	//4.关闭socket对象 
	close(tcp_socket);	
	return 0;
}

sqlite3文件

这里是sqlite3数据库的操作 需要在server.c中进行操作
typedef struct Student
{
	int id;
	char name[SIZE];
	float score;
}stu;
//打开数据库
//参数:数据库名
sqlite3 *sql_open(char *dbname)
{
	sqlite3 *db = NULL;
	int ret = sqlite3_open(dbname,&db);
	if(ret != SQLITE_OK)
	{
		perror("sqlite open error!\n");
		return NULL;
	}
	printf("sqlite open ok\n");
	return db;
}
//创建表
//参数1:数据库的连接对象 sqlite3 *
//参数2:表的名称   char *tbname
int create_table(sqlite3 *db,char *tbname)
{
	char sql[N] = {'\0'};
	sprintf(sql,"create table if not exists %s (id int primary key not null,name text,score real)",tbname);
	printf("%s\n",sql);
	char *errmsg = NULL;
	int ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
	if(ret != 0)
	{
		fprintf(stderr,"%s\n",errmsg);
		return -1;
	}
	else
	{
		printf("create table ok!\n");
	}
	return 0;
}
//增加内容
//参数1:数据库的连接对象
int data_insert(sqlite3 *dbname,char *tbname)
{
	stu s1;
	printf("请输入ID 姓名和成绩:");
	scanf("%d%s%f",&s1.id,s1.name,&s1.score);
	//增加
	char *errmsg = NULL;
	char sql[N] = {'\0'};
	sprintf(sql,"insert into %s values (%d,'%s',%.1f)",tbname,s1.id,s1.name,s1.score);
	printf("%s\n",sql);
	int ret = sqlite3_exec(dbname,sql,NULL,NULL,&errmsg);
	if(ret != SQLITE_OK)
	{
		fprintf(stderr,"%s\n",errmsg);
		return -1;
	}
	else
	{
		printf("insert ok!\n");
	}
	return 0;
}
//删除 
int data_delete(sqlite3 *dbname,char *tbname)
{
	stu s1;
	printf("请输入要删除的ID号:");
	scanf("%d",&s1.id);
	char sql[N] = {'\0'};
	sprintf(sql,"delete from %s where id = %d",tbname,s1.id);
	printf("%s\n",sql);
	char *errmsg = NULL;
	if(sqlite3_exec(dbname,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%s\n",errmsg);
		return -1;
	}
	else
	{
		printf("delete ok!\n");
	}
	return 0;
}
//更新 
int data_update(sqlite3 *dbname,char *tbname)
{
	stu s1;
	printf("请输入要修改的ID:");
	scanf("%d",&s1.id);
	printf("要修改的成绩为:");
	scanf("%f",&s1.score);
	char sql[N] = {'\0'};
	sprintf(sql,"update %s set score = '%.1f' where id = %d",tbname,s1.score,s1.id);
	printf("%s\n",sql);
	char *errmsg = NULL;
	if(sqlite3_exec(dbname,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%s\n",errmsg);
		return -1;
	}
	else
	{
		printf("update ok!\n");
	}
	return 0;
}
//查询的回调函数
//参数1:void * data给回调函数传递参数
//参数2:int columnNum 记录中包含的段数目(几列就是几)
//参数3:char ** //char *columnValue[] 列值
//参数4:char ** //char *columnName[]	名字
int callback(void *data,int columnNum,char *columnValue[],char *columnName[])
{
	int i = 0;
	stu s1;
	memset(&s1,'\0',sizeof(s1));
	s1.id =atoi(columnValue[0]);
	strcpy(s1.name,columnValue[1]);
	s1.score =atof(columnValue[2]);
	printf("%5d%10s%7.1f\n",s1.id,s1.name,s1.score);
	printf("\n");
	return 0;
}
//查询内容
//参数1:数据库的连接对象 
//参数2:表名
int data_select(sqlite3 *dbname,char *tbname)
{
	char sql[N]= {'\0'};
	sprintf(sql,"select * from %s",tbname);
	char *errmsg = NULL;
	//参数1:连接对象sqlite3 *db 
	//参数2:sql语句
	//参数3:回调函数 函数的指针 //select
	//参数4:给回调函数传参
	int ret = sqlite3_exec(dbname,sql,callback,NULL,&errmsg);
	if(ret != SQLITE_OK)
	{
		fprintf(stderr,"%s\n",errmsg);
		return -1;
	}
	else
	{
		printf("select ok!\n");
	}
	return 0;
}
  1. 这基本的框架就是这样,然后进行登陆注册的增删改查以及项目内容的增删改查,这里是大家自由发挥的时间,可以根据自己的需求进行项目完善。

最后,咋们可以根据这个框架进行升级

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言网络编程聊天室是一个基于TCP/IP协议的聊天程序,可以在Linux操作系统上使用。它可以通过socket和多线程实现,也可以使用UDP或epoll来处理高并发。该聊天室可以支持多个客户端与服务器进行实时通信,并允许用户加入和退出不同的聊天室。 实现C语言网络编程聊天室的主要步骤包括: 1. 需求分析:确定聊天室的功能需求。 2. 学习TCP/IP协议:理解C/S模型、socket编程的常规步骤以及阻塞与非阻塞socket等概念。 3. 文件操作和数据库:学习如何进行文件操作和数据库的操作,以便存储聊天记录和用户信息等。 4. 实现思路:考虑如何设计服务器和客户端之间的通信方式,以及如何处理多个客户端的并发连接。 5. 编代码:根据需求和思路,编服务器和客户端的代码。 6. 运行测试:运行服务器和客户端程序,检查是否能够实现实时通信和聊天室的基本功能。 如果要退出聊天室,可以使用exit_chatroom函数。该函数会遍历聊天室列表,找到用户所在的聊天室,并将用户从聊天室中移除。如果用户未加入聊天室,则会返回相应的提示信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [C语言练手项目--C 语言编聊天室](https://blog.csdn.net/qq_38880380/article/details/84979553)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [网络编程基础,纯C语言实现聊天室(附源代码)——从铁矿到钢铁的打造](https://blog.csdn.net/weixin_43164603/article/details/107301548)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值