聊天室 思路

要求

实现一个简单的聊天室,有私聊,群聊和发送文件等功能,以及一些小细节。

服务端

首先是创建套接字,初始化套接字,以及连接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的问题…

如果有问题,希望可以指出。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值