04/16周末作业

基于UDP的网络聊天室

ser

#include "head.h"

#define ERR_MSG(msg) do{\
	fprintf(stderr,"line:%d\n",__LINE__);\
	perror(msg);\
}while(0)

#define IP "192.168.0.103 "  //本机IP ifconfig
#define PORT 2048            //1024-49151

//定义结点结构体
typedef struct Node
{
	//数据域:
	union{
		int len;		//头结点的数据域
		struct sockaddr_in addr;
	};
	//指针域:下一个结点的地址
	struct Node *next;

}*Linklist;
struct msg
{
	char type; 	//'L'登录 'C'chat 'Q'下线
	char name[20];
	char text[128];
};

/*
 * function:    在堆区创建头结点
 * @param [ in] 无参数
 * @param [out] 
 * @return      成功返回头结点地址,失败返回NULL
 */
Linklist Create_head()
{
	Linklist L = (Linklist)malloc(sizeof(struct Node));
	if(L == NULL)
		return NULL;
	L->len = 0;
	L->next = NULL;
	return L;
}

/*
 * function:    创建其他结点
 * @param [ in] 无参数
 * @param [out] 
 * @return      成功返回首地址,失败返回NULL
 */
Linklist Create_node()
{
	Linklist p = (Linklist)malloc(sizeof(struct Node));
	if(p == NULL)
		return NULL;
	//p->addr = NULL;
	p->next = NULL;
	return p;
}

/*
 * function:    头插  永远在头结点后面
 * @param [ in] 头结点   插入的数据元素
 * @param [out] 
 * @return      成功返回0,失败返回-1
 */
int Insert_head(Linklist L,struct sockaddr_in e)
{
	//判断头结点是否存在
	if(L == NULL)
	{
		printf("头插入失败。\n");
		return -1;
	}
	//在堆区申请其他结点空间
	Linklist p = Create_node();
	//p的数据赋值为e
	p->addr = e;
	//p的指针域
	p->next = L->next;
	L->next = p;
	//链表长度自增
	L->len++;
	return 0;
}
#if 1
/*
 * function:    链表的遍历
 * @param [ in] 链表
 * @param [out] 
 * @return      无返回值函数
 */
void Output(Linklist L)
{
	//1.判断头结点是否存在
	//2.判断链表是否为空
	if(L == NULL || L->len == 0)
		printf("输出失败!\n");
	while(L->next)
	{
		L = L->next;
	//	printf("%s\t",L->addr);
	}
	printf("\n");
}

/*
 * function:    按元素查找
 * @param [ in] 链表   元素  
 * @param [out] 
 * @return      成功返回位置,失败返回-1
 */
int Search_by_data(Linklist L,struct sockaddr_in e)
{
	//判断头结点是否存在
	//判断链表是否为空
	if(L == NULL || L->len == 0)
	{
		printf("失败。\n");
		return -1;
	}
	Linklist p = L;
	for(int i=0;i<L->len;i++)
	{
		p = p->next;
		if(p->addr.sin_port == e.sin_port)
			return i+1;
	}
	return -1;

}

/*
 * function:    按位置删除
 * @param [ in] 链表   删除的位置
 * @param [out] 
 * @return      成功返回0,失败返回-1
 */
int Delete_by_pos(Linklist L,int pos)
{	
	//判断头结点是否存在
	//判断位置是否合法
	if(L == NULL || L->len == 0 || pos<1 || pos>L->len)
	{
		printf("失败。\n");
		return -1;
	}
	//找到pos-1的位置,起名字为p
	Linklist p = L;
	for(int i=0;i<pos-1;i++)
		p = p->next;
	Linklist s = p->next;
	p->next = s->next;
	free(s);
	s = NULL;
	L->len--;
	//Delete_head(p);

	return 0;

}

/*
 * function:    按元素删除
 * @param [ in] 链表   元素  
 * @param [out] 
 * @return      成功返回0,失败返回-1
 */
int Delete_by_data(Linklist L,struct sockaddr_in e)
{
	//先找e位置
	int pos = Search_by_data(L,e);
	if(pos ==-1)
		return -1;
	//再根据位置删除
	int flag = Delete_by_pos(L,pos);
	if(flag == -1)
		return -1;
	return 0;
}
#endif

int do_login();
int main(int argc, const char *argv[])
{
	Linklist L = Create_head();//创建头结点
	//创建报式套接字
	int sfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sfd < 0)
	{
		ERR_MSG("socket");
		return -1;
	}

	//填充服务器的地址信息结构体
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET; 	 		//必须填AF_INET;
	sin.sin_port 		= htons(PORT); 		//端口号的网络字节序
	sin.sin_addr.s_addr = inet_addr(IP);  	//本机IP地址
 	
	//绑定 必须绑定
	if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		ERR_MSG("bind");
		return -1;
	}

	struct sockaddr_in cin;
	socklen_t addrlen = sizeof(cin);

	struct msg sndbuf;
	strcat(sndbuf.name,"**system**");

	//创建进程
	pid_t cpid = fork();
	//父进程用于接收
	if(cpid > 0)
	{
		while(1)
		{
			struct msg rcvbuf;
			recvfrom(sfd, &rcvbuf, sizeof(rcvbuf),0, (struct sockaddr*)&cin, &addrlen);

			//printf("type = %c\n", rcvbuf.type);
			//printf("name = %s\n",rcvbuf.name);
			//printf("%d\n",ntohs(cin.sin_port));
			switch(rcvbuf.type)
			{
			case 'L':
				Insert_head(L,cin);
				Linklist q = L->next;
				while(q != NULL)//群发
				{
					rcvbuf.type = 'L';
					if(sendto(sfd,&rcvbuf,sizeof(rcvbuf),0,(struct sockaddr*)&q->addr,sizeof(q->addr)) < 0)
					{
						ERR_MSG("sendto");
						return -1;
					}
					q = q->next;
				}
				printf("用户[%s]登陆成功\n",rcvbuf.name);

				//do_login();
				break;
			case 'C':
				printf("[%s]: %s\n",rcvbuf.name,rcvbuf.text);
				Linklist p = L->next;
				while(p != NULL)//群发
				{
					rcvbuf.type = 'C';
					if(sendto(sfd,&rcvbuf,sizeof(rcvbuf),0,(struct sockaddr*)&p->addr,sizeof(p->addr)) < 0)
					{
						ERR_MSG("sendto");
						return -1;
					}
					p = p->next;
				}

				//do_chat();
				break;
			case 'Q':
				Delete_by_data(L,cin);
				Linklist t = L->next;
				while(t != NULL)//群发
				{
					rcvbuf.type = 'Q';
					if(sendto(sfd,&rcvbuf,sizeof(rcvbuf),0,(struct sockaddr*)&t->addr,sizeof(t->addr)) < 0)
					{
						ERR_MSG("sendto");
						return -1;
					}
					t = t->next;
				}
				printf("[%s]已下线\n",rcvbuf.name);
				//do_quit();
				break;
			}
		}
	}
	//子进程用于发送
	else if(0 == cpid)
	{
		while(1)
		{
			memset(sndbuf.text,0,sizeof(sndbuf.text));
			scanf("%s",sndbuf.text);
		//	Linklist q = L->next;
		//	while(q != NULL)//群发
		//	{
				sndbuf.type = 'C';
				if(sendto(sfd,&sndbuf,sizeof(sndbuf),0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
				{
					ERR_MSG("sendto");
					return -1;
				}
		//		q = q->next;
		//	}
		}
	}

	//关闭文件描述符
	close(sfd);
	return 0;
}

int do_login()
{
	//转发---->遍历链表
	//保存客户端信息
	
}

cli

#include "head.h"

#define ERR_MSG(msg) do{\
    fprintf(stderr, "line:%d ", __LINE__);\
    perror(msg);\
}while(0)                                                                                     

#define CLI_IP "192.168.0.103"   //本机IP ifconfig
#define CLI_PORT 2048           //1024-49151

struct msg
{
    char type;  //'L'登录 'C'chat 'Q'下线
    char name[20];
    char text[128];
};


int main(int argc, const char *argv[])
{
	//创建报式套接字
	int cfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(cfd < 0)
	{
		ERR_MSG("socket");
		return -1;
	}

	//bind  非必须绑定
	//如果不绑定则由操作系统自动绑定IP和端口


	//填充服务器的地址信息结构体,给sendto函数使用
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET; 	 			//必须填AF_INET;
	sin.sin_port 		= htons(CLI_PORT); 		//端口号的网络字节序
	sin.sin_addr.s_addr = inet_addr(CLI_IP);  	//服务器IP地址
	
	struct msg sndbuf;
	sndbuf.type = 'L'; 	//登录请求
	printf("请输入ID>>> ");
	scanf("%s",sndbuf.name);
	//strcpy(sndbuf.name, "aaa");
	//发送数据,发送给服务器
	if(sendto(cfd, &sndbuf, sizeof(sndbuf), 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		ERR_MSG("sendto");
		return -1;
	}
	//printf("发送成功\n");


	struct sockaddr_in rcvaddr; 	//存储数据包是从谁哪里来的
	socklen_t addrlen = sizeof(rcvaddr);
	//创建进程
	pid_t cpid = fork();
	//父进程用于发送
	if(cpid > 0)
	{
		while(1)
		{
			memset(sndbuf.text, 0, sizeof(sndbuf.text));
			//printf("请输入>>> ");
			scanf("%s",sndbuf.text);
			if(strcmp("quit",sndbuf.text) == 0)
			{
				sndbuf.type = 'Q';   //下线请求	
				//发送数据给客户端
				if(sendto(cfd,&sndbuf,sizeof(sndbuf),0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
				{
					ERR_MSG("sendto");
					return -1;
				}
				exit(0);
			}
			else
			{
				sndbuf.type = 'C';   //聊天请求	
				//发送数据给客户端
				if(sendto(cfd,&sndbuf,sizeof(sndbuf),0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
				{
					ERR_MSG("sendto");
					return -1;
				}

			}
		}
	}
	//子进程用于接收
	else if(0 == cpid)
	{
		while(1)
		{
			struct msg rcvbuf;
			recvfrom(cfd, &rcvbuf, sizeof(rcvbuf),0, (struct sockaddr*)&rcvaddr, &addrlen);
			if(strcmp(rcvbuf.name,sndbuf.name) == 0)
				continue;

			//printf("type = %c\n", rcvbuf.type);
			//printf("name = %s\n",rcvbuf.name);
			//printf("%d\n",ntohs(sin.sin_port));
			switch(rcvbuf.type)
			{
			case 'L':
				printf("[%s]登陆成功\n",rcvbuf.name);		
				memset(&rcvbuf,0,sizeof(rcvbuf));
				//do_login();
				break;
			case 'C':
				printf("[%s] :%s\n",rcvbuf.name,rcvbuf.text);
				memset(&rcvbuf,0,sizeof(rcvbuf));
				//do_chat();
				break;
			case 'Q':

				printf("[%s]已下线\n",rcvbuf.name);
				//do_quit();
				break;
			}
		}

	}

	//关闭文件描述符
	close(cfd);
	return 0;
}


单词导入

 sqlite3.c

#include "head.h"


int main(int argc, const char *argv[])
{	
	char sql[128] = "";
	char* errmsg = NULL;
	//如果数据库不存在,则创建后直接打开
	//如果存在则直接打开
	sqlite3* db;
	if(sqlite3_open("./my.db",&db) != SQLITE_OK)
	{
		fprintf(stderr,"sqlite3_open : %s errcode : %d\n",sqlite3_errmsg(db),sqlite3_errcode(db));
		return -1;
	}
	printf("sqlite3_open success\n");

	//创建一个表
	//注意:C代码中编写的sql语句与在数据库中编写一致
	strcat(sql,"create table if not exists stu (id int,word char,fanyi float);");

	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
	{
		fprintf(stderr,"line: %d  sqlite3_exec: %s\n",__LINE__,errmsg);
		return -1;
	}
	printf("create table stu success\n");

	char c = 0;
	while(1)
	{
		system("clear");
		printf("------------------------\n");
		printf("--------1. 增-----------\n");
		printf("--------2. 删-----------\n");
		printf("--------3. 改-----------\n");
		printf("--------4. 查-----------\n");
		printf("--------5. 导入---------\n");
		printf("--------6. 退出---------\n");
		printf("------------------------\n");
		printf("请选择功能>>> ");
		c = getchar();
		while(getchar() != 10);

		switch(c)
		{
			case '1':
				do_insert(db);
				break;
			case '2':
				do_delete(db);
				break;
			case '3':
				do_update(db);
				break;
			case '4':
				do_select(db);
				break;
			case '5':
				do_insertall(db);
				break;
			case '6':
				goto END;
				break;
			default:
				printf("输入错误,请重新输入\n");
		}
		printf("输入任意字符清屏>>> \n");
		while(getchar() != 10);

	}

END:
	//关闭数据库
	if(sqlite3_close(db) != SQLITE_OK)
	{
		fprintf(stderr,"sqlite3_close : %s errcode : %d\n",sqlite3_errmsg(db),sqlite3_errcode(db));
		return -1;
	}

	return 0;
}

func.c

#include "head.h"

void do_insert(sqlite3* db)
{
	char sql[128] = "";
	char* errmsg = NULL;
	int id;
	char name[32] = "";
	float score;

	printf("请输入id>>> ");
	scanf("%d",&id);
	while(getchar() != 10);
	printf("请输入name>>> ");
	scanf("%s",name);
	while(getchar() != 10);
	printf("请输入score>>> ");
	scanf("%f",&score);
	while(getchar() != 10);

	sprintf(sql,"INSERT INTO stu VALUES (%d,\"%s\",%g);",id,name,score);

	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
	{
		fprintf(stderr,"line: %d  sqlite3_exec: %s\n",__LINE__,errmsg);
		return ;
	}
	printf("增 成功\n");

	return ;
}
void do_delete(sqlite3* db)
{
	char sql[128] = "";
	char* errmsg = NULL;
	int id;
	printf("输入要删除信息的id号>>> ");
	scanf("%d",&id);
	sprintf(sql,"DELETE FROM stu WHERE id = %d;",id);
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
	{
		fprintf(stderr,"line: %d  sqlite3_exec: %s\n",__LINE__,errmsg);
		return ;
	}
	printf("删 成功\n");

	return ;
}
void do_update(sqlite3* db)
{
	char sql[128] = "";
	char* errmsg = NULL;
	int id;
	char update[32] = "";
	float score;
	printf("输入修改的字段>>> ");
	scanf("%s",update);
	printf("输入修改后的值>>> ");
	scanf("%f",&score);
	printf("输入id>>> ");
	scanf("%d",&id);
	sprintf(sql,"UPDATE stu SET %s = %f WHERE id = %d;",update,score,id);	
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
	{
		fprintf(stderr,"line: %d  sqlite3_exec: %s\n",__LINE__,errmsg);
		return ;
	}
	printf("改 成功\n");

	return ;
}
/*
int select_callBack(void *arg,int columns,char **column_text,char **column_name)
{
	if(0 == *(int*)arg)
	{
		for(int i=0;i<columns;i++)
		{
			printf("%s\t",column_name[i]);
		}
		putchar(10);
		*(int*)arg = 1;
	}

	for(int i=0;i<columns;i++)
	{
		printf("%s\t",column_text[i]);
	}
	putchar(10);
	return 0;
}
*/
int do_select(sqlite3* db)
{
	int flag = 0;
	char** pres = NULL;
	int row,column;
	char sql[128] = "";
	char* errmsg = NULL;

	sprintf(sql,"select * from stu;");

	if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK)
	{
		fprintf(stderr,"line: %d  sqlite3_get_table: %s\n",__LINE__,errmsg);
		return -1;
	}
	printf("row = %d  column = %d\n",row,column);

	int index = 0;
	for(int i=0;i<(row+1);i++)
	{
		for(int j=0;j<column;j++)
			printf("%s\t",pres[index++]);
		putchar(10);
	}
	putchar(10);
#if 0
	for(int i=0;i<(row+1)*column;i++)
	{
		printf("%s\t",pres[i]);
		if(i%column == column-1)
			putchar(10);
	}
#endif 
	sqlite3_free_table(pres);
	pres = NULL;
	printf("查 成功\n");

	return 0;
}
int do_insertall(sqlite3* db)
{
	//打开一个文件
	FILE *fp=fopen("./dict.txt","r");
	if(NULL==fp)
	{
		perror("fopen");
		return -1;
	}
	//printf("电子词典正在导入请稍后>>>\n");
	//指定的文件中格式化获取数据
	//存储每一行数据
	char buf[512]="";
	char get_word[128]="";
	char get_fanyi[128]="";
	char sql[128]="";
	char *errmsg=NULL;
	int id = 0;
	//循环读取每一行内容
	while(1)
	{
		id++;
		bzero(get_word,sizeof(get_word));
		bzero(get_fanyi,sizeof(get_fanyi));
 
		if(fgets(buf,sizeof(buf),fp)==NULL)
		{                                                                                               
			printf("单词导入完毕\n");
			return -1;
		}
		buf[strlen(buf)-1]='\0';

		for(int i=0;buf[i]!='\0' ;i++)
		{
			if(buf[i]==' ' && buf[i+1]==' ')
			{
				strncpy(get_word,buf,i);
			}
			if(buf[i]==' ' && buf[i+1]==' ' && buf[i+2]!=' ')
			{
				strcpy(get_fanyi,buf+i+2);
				break;
			}
		}
		bzero(sql,sizeof(sql));
		sprintf(sql,"insert into stu values(%d,\"%s\",\"%s\");",id,get_word,get_fanyi);
 
		if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
		{
			fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
			return -1;
		}
	}
	//关闭文件描述符
	fclose(fp);
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值