C语言聊天室项目说明书

网络聊天室项目说明

  • 项目的目的和意义

该聊天室项目为利用linux下C语言网络编程相关知识,采用Server/Client,即服务器与客户端的基本框架实现。整个项目涉及了socket套接字,线程,嵌入式数据库sqlite3,select模型等多个知识模块,服务器整体采用select模型,并不断监听客户端,客户端中起一个线程,用来实时接受服务器发送的信息。

该聊天室项目可模拟当今的聊天工具中的各个功能,实现最基本的互相发送信息,群发消息,登陆注册等功能。完成该项目可很大的提高我们初学者的编程能力,以及面对出现的各种bug的应对解决能力,是一个提升自我的很好途径。

 

  • 项目的需求分析

1.聊天室支持连接多个客户端,采用select模型

2.客户端与服务器的连接,接受信息

3.账号网名的注册,登录,并存档

4.显示所以在线好友

5.服务器与客户端的通信,实现信息转发(私聊,群聊)

6.实现管理员权限,可进行禁言,踢人等功能

7.发送表情,常用语句

8.每个用户都建立各自的聊天记录文件,服务器保存所以用户的聊天记录

 

 

  • 项目的技术方案设计
  1. 服务器socket和select

首先建立socket,用bind进行绑定后,用listen进行对客户端的监听。在一个while(1)循环中,采用select对客户端进行操作,将所以文件描述符放到readfd中,如果是有新的客户端要进行连接,即sockfd有动静,就开始accept操作,将新的fd放到readfd中,并修改maxfd的值;如果是其他已经存在的fd有动作,则进行聊天室相关的功能操作。

 

  1. 客户端的实现

先建立socket,用connect与服务器进行连接,此后先进入账号登陆注册的函数,登陆成功后,及账号函数执行完毕,此时起一个线程,用来实时接受服务器端发送的信息。之后调用聊天室的各种功能的实现函数。在线程中,不断接受服务器发送的信息,根据标志位实现各个功能,如私聊位是1,就进行打印收到的信息内容。

 

  1. 账号注册登录

这是需要打开一个数据库,用来存放帐号密码网名的信息。注册时,要进行判断该账号是否已经存在,将其与账号数据库中的账号进行逐一比较,若存在相同的则将一个标志位置一,显示该帐号已存在,在输入网名时进行同样的查重操作。登陆时,输入账号时判断该帐号是否已经登录,以及是否存在,输入密码后与数据库相应位置的信息比较,判断密码的对错。当登陆成功后,将登陆的id,网名信息发送给服务器,服务器形成一个链表,用来存放在线用户的信息,包含网名所对应的文件描述符fd,以便后期使用,登录时输入账号查看是否在已经在线就是向服务器发送一个信号,在服务器端遍历该链表,查看是否在线,再发送回客户端。

 

  1. 私聊群聊

在客户端处选择该功能,输入发送对象的网名,然后就可以输入信息并发送。定义一个用来专门发送信息的struct,Sendbuf,设置私聊的标志位,私聊时将其置一,服务器端判断该位如果是一就进行私聊操作,将网名和发送的内容分别存放到Sendbuf中,服务器接收到后,根据网名来遍历在线用户链表,查找到相应的fd,再将信息转发给该用户,若是群聊,就将信息转发给链表中的所以用户。

 

  1. 管理员功能

在每个客户端设置一个管理员标志位,初始化为0,若选择注册会员功能,则将其置一,否在在选择禁言踢人等功能时显示无权限。禁言时输入禁言对象,服务器转发禁言消息给该用户,该用户的不可发言标志位置一,则不能进行私聊群聊。踢人时输入网名,服务器向其发送退出信号,则该客户端退出聊天室,及进程被终止。

 

  1. 发送表情,常用语

设置特有的标识符代表相应表情和常用语句,之后进行私聊操作,发送相应的表情和常用语。

 

  1. 保存聊天记录

在客户端的私聊群聊发送表情常用语功能处,发送之后将其内容和发送者发送对象的网名存放到相应用户的数据库表中,在接受端同样进行该操作,即可保存用户的聊天记录。在服务器端,进行转发操作时,将发送者发送对象网名和聊天内容存放到系统的聊天记录文件中,便实现了服务器端的聊天记录保存。

 

四、遇到的问题与解决途径及方法

1.重复登录的问题

问题:由于每个id登陆后,在接受消息发送消息时,都会打开用其id命名的数据库表,如果同时登录了一个账号,在接受发送消息时,两个进程会同时打开一个数据库表,这时就会exec函数就会出错,进程退出。

 

解决方法:这时就需要限制帐号的重复登录,保证一个账号只能登录一次,在登陆的时候,将输入的id号发送给服务器,遍历服务器中在线用户信息的链表,若已存在则打印该帐号已登录。这样就可以保证每个帐号只能登陆一次。

 

  1. 退出时出现的问题

问题:在一个客户端退出时,如果没有相应的操作,在服务器端该客户端的相关信息还是存在的,在其他用户聊天查看好友时会出现问题,并且此时若有其他客户端连接,所产生的fd也会出错,所以在退出时一定要有相关操作。程序异常退出时,如遇到ctrl+c信号,也应有相应操作。

 

解决方法:遇到ctrl+c信号时,客户端应获取该信号,即SIGINT,获取后执行一个函数,用来关闭相应的fd,并在服务器端删除该用户的在线信息。在功能选择界面也添加一个退出选项,执行相关操作。

 

  1. MaxFd的改变问题

问题:在同时连接了几个客户端后,通讯都正常,但是关闭中间的客户端时,会出现之后开启的客户端无法与服务器通信的现象。

 

解决方法:在调试了多次之后,发现问题出在MaxFd的改变上,MaxFd必须要比select中的那个readfd中的最大的成员的fd的数值要大,如果小了,就会出线上述问题,造成之后的fd无法通信。在每次有客户端退出时,一定要将fd数组中的所以fd遍历一遍,找到最大的再赋值给MaxFd,一定要确保MaxFd足够大才可以。

 

  1. 功能选择输入时输入出错的问题

问题:由于各个功能的选择标号是int型,正常应该输入一个数字,但如果随便输入各种字符的话就会出错,并且由于缓冲区的问题,会继续影响之后的功能选择

 

解决方法:分两步,scanf这个函数也是有返回值的,如果没有获取成功会返回0,可以通过这个来判断是否获取到了int型数据,如果失败了,就需要进行清除缓冲区,查找了资料,可以用while((ch = getchar()) != EOF && ch != ‘\n’);来进行清除缓冲区。

 

猜你喜欢

转载自blog.csdn.net/cb673335723/article/details/81083513
今日推荐