要求
实现一个简单的聊天室,有私聊,群聊和发送文件等功能,以及一些小细节。
服务端
首先是创建套接字,初始化套接字,以及连接mysql库,
然后通过epoll对accept到的客户端的套接字进行一些初始化,
如果有写事件传入,创建一个线程,对事件进行处理。
最后,要关闭mysql库,关闭套接字。
客户端
首先也是创建套接字,初始化套接字的一些操作,
然后创建两个线程,一个用于收包,一个用于接包,
在线程对事件进行处理。
遇到的一些问题
-
发包和收包的问题
在私聊和群聊下,发送消息给其他人,是通过不同的套接字来发送消息的。
-
消息的输入问题
消息中,如果包括空格,单纯的使用scanf("%s",buf)就无法读入空格,消息的发送就会出现一些问题。
聊天室中使用的是scanf("%[^\n]",buf);
使用%[^\n]就可以一直输入,直到碰到’\n’才结束读入。
使用%[^\n]不会读入\n,\n还保留在缓冲区中,所以在scanf后面要加上getchar()。想看例子点这里
%[^\n]这是scanf的正则用法,关于scanf的正则用法,想了解更多点这里
-
密码加密问题
在Linux下,无法使用getch,无法实现密码加密,所以设置终端 的显示,调用的是tcgetattr和tcsetattr两个函数。
需要了解的一些关于tcgetattr的知识
//聊天室中关于密码加密的代码
void getpasswd(char *passwd)
{
struct termios oldt, newt;
char ch;
tcgetattr(0, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
int i = 0;
while(1)
{
tcsetattr(0, TCSANOW, &newt);
ch = getchar();
tcsetattr(0, TCSANOW, &oldt);
if(ch=='\n')
{
passwd[i]='\0';
break;
}
passwd[i]=ch;
i++;
printf("*");
}
printf("\n");
}
-
文件传输问题
文件的传输,同样是通过发包和收包来实现的,由一个客户端发到服务器,再由服务端发向另一个客户端。
在第一次检查的时候,我发送的不论是在服务器还是在客户端中的文件,最后都有一行\00\00…
查找了资料,发现 recv 和 send 都针对的是字符(无边界), 而不是字符串(以’\0’作为边界)。所以,在传送包的时候,\0也会被传送过来,所以文件中有一大堆的\00\00…,可以通过 recv 和 send 的返回值,也就是接收收据的字节数,来对文件进行写入,而\00\00…不写入,这样文件传输,就不会出现一大堆\00\00… 的问题。(参考资料)
文件传输的问题,还要注意当前指针所在的位置,避免重复写入文件。
聊天室的文件传输,没有办法传输图片,不知道是哪里出现了问题,现在还不会改,先找一下解决办法。
-
帐号创建的问题
聊天室的群聊帐号,我是通过数据库中行数来分配帐号的,然后在检查中,创建了两个群,在第一个群解散后,再创建一个群,分配到的帐号与第二个群的帐号一样,出现了两个群群号相同的问题。在修改的时候,考虑到群就算解散了,还是会有聊天记录在,我就换了一种群号增加的方式来分配群号,就不会再出现群号相同的问题了。
//关于创建群聊的代码
int create_gro(bag *recv_bag)
{
bag *bag1=recv_bag;
int j=999;
MYSQL_RES *result=NULL;
MYSQL_ROW row,row1;
char sql[1280];
int ret;
gro *group;
group=(gro *)malloc(sizeof(gro));
memset(sql,0,sizeof(sql));
sprintf(sql,"select * from gro");
pthread_mutex_lock(&mutex);
ret=mysql_query(&mysql,sql);
if(!ret)
{
result=mysql_store_result(&mysql);
while(row=mysql_fetch_row(result))
{
if(j<atoi(row[0]))
{
j=atoi(row[0]);
}
}
j++;
group->gro_id=j;
strcpy(bag1->write_buf,"success");
sprintf(bag1->recv_id,"%d",group->gro_id);
memset(sql,0,sizeof(sql));
sprintf(sql,"select * from 身份信息 where id ='%s'",bag1->send_id);
mysql_query(&mysql,sql);
result=mysql_store_result(&mysql);
row1=mysql_fetch_row(result);
strcpy(group->gro_name,row1[1]);
group->gro_mem_id=atoi(bag1->send_id);
memset(sql,0,sizeof(sql));
sprintf(sql,"insert into gro values (%d, %d,'%s',2) ",group->gro_id,group->gro_mem_id,group->gro_name);
mysql_query(&mysql,sql);
}else{
strcpy(bag1->write_buf,"failed");
}
send(bag1->recv_fd,bag1,sizeof(bag),0);
pthread_mutex_unlock(&mutex);
return 0;
}
-
一些小细节
getchar()的添加问题,malloc的问题…
如果有问题,希望可以指出。