嵌入式Linux下的聊天程序.docx
《嵌入式Linux下的聊天程序.docx》由会员分享,可在线阅读,更多相关《嵌入式Linux下的聊天程序.docx(18页珍藏版)》请在冰豆网上搜索。
![嵌入式Linux下的聊天程序.docx](https://file1.bdocx.com/fileroot1/2023-2/22/7441dd0a-dc39-48e7-8280-71a464447377/7441dd0a-dc39-48e7-8280-71a4644473771.gif)
嵌入式Linux下的聊天程序
华中科技大学
《嵌入式Linux软件设计》
课程设计报告
姓名
学号
班级
题目嵌入式Linux下的聊天程序
成绩
评语
日期2011年6月24日
目录:
目录
I.项目名称嵌入式Linux下的聊天程序3
II.项目需求分析3
A.设计目标3
1.基本功能3
2.扩展功能3
B.设计思路3
C.实现方法3
III.项目分工3
IV.概要设计:
4
A.基本功能流程框图4
B.模块的划分与描述5
V.详细设计:
5
A.服务器端群聊功能模块:
见同组成员杨的报告5
B.客户端基本功能5
C.扩展功能:
6
1.聊天记录查询功能:
6
2.私聊功能:
见同组成员杨处7
3.多聊功能:
7
4.功能提示模块:
见同组队员报告7
5.报错功能:
7
D.编程中调用的头文件8
E.方案选择9
F.经验教训9
VI.调试结果与改进方案10
A.运行说明10
1.PC机上:
10
2.ARM上:
10
B.运行结果及说明:
11
C.改进方案:
15
VII.实验总结15
VIII.参考文献15
I.项目名称嵌入式Linux下的聊天程序
II.项目需求分析
A.设计目标
1.基本功能
在实验箱上运行服务器程序,可同时接入多个的客户端,每个客户端有自己的标识,均可看到所有客户端的发言,客户端的退出能够退出而不影响服务器,并给其他客户端提示。
2.扩展功能
单聊:
即私聊,一对一聊天
多聊:
一对多人聊天,可非全部所以客户端
群聊:
广播式聊天,一对所有client
查询聊天记录:
查询在群聊过程中的聊天记录
完善的报错:
在错误输入及格式下报错
友好的提示:
提示用户相关功能使用方法
B.设计思路
要实现网络聊天室的功能,可以采用C/S方式,要让每个客户端都可以看到所有客户端的发言,可以将服务器当做一个消息中转站,每个在聊天室中发言的客户端,都先将消息发送给服务器,再由服务器将该消息转发给其他所有客户端,响应客户端的查询聊天记录、单聊、多聊等附加功能。
同时在服务器上通过网络IP或者socket号来标识每个客户端。
C.实现方法
在Linux操作系统环境下使用socket接口编程实现,传输层使用TCP协议,即采用流式套接字,实现端到端可靠的消息传递。
使用非阻塞式的select()函数处理I/O多路复用的情况,实现的多人聊天等几个功能,扩展功能的代码都加在send_to_others()中,通过匹配识别加if条件选择的方法去判断到底该执行哪一个基本功能或者扩展功能
III.项目分工
同组成员:
杨
分工实现功能:
杨:
基本功能中服务器部分的设计,扩展功能部分中:
私聊,群聊,提示功能
陈:
基本功能中客户端部分的设计,扩展功能部分中:
多聊,聊天记录,报错功能
共同完成算法设计、基本代码的编写和调试,报告的书写。
完成情况:
均顺利完成
IV.概要设计:
A.基本功能流程框图
B.模块的划分与描述
系统采用客户/服务器工作模式,服务器端主要由三个部分组成,包括main(),get_sock()和send_to_others(),还有一个错误处理函数errexit()。
get_sock()函数是用于创建监听流套接口,将本地IP与监听socket绑定,准备接收有限个客户端的连接请求。
Send_to_others()函数是实现服务器的中转作用,即将某个客户端发来的消息向其它客户端转发,实现群发功能,多聊功能、单聊功能、查看聊天记录等功能。
Main()函数中是TCP的工作流程,包含了socket的建立、监听、绑定、等待接收、发送、接收及关闭等部分,其中一个很重要的调用函数是select()函数,其主要功能是同时判断多个套接口的多种状态,实现I/O复用,实现一个服务器对多个客户端的通信,另外客户端还实现了以套接字号作为客户端的标志返回及输入格式提示。
客户端的程序相对服务器较小,只用完成一个客户端对一个服务器的数据交互,基本思想和实现与服务器相同,所以只包含一个main()函数,其中需要调用套接口的建立、连接和数据的发送和接收等基本函数,也要用到select函数,用于用户输入消息发送和接收消息读取的I/O复用,另有select()函数调用错误的各种提示信息显示。
简而言之,我们分为服务器的基本功能模块(即群聊功能)、客户端的基本功能模块,服务器端附加功能:
聊天记录模块、单聊功能模块、多聊功能模块、较为完善的报错功能、使用提示提示模块。
V.详细设计:
A.服务器端群聊功能模块:
见同组成员杨的报告
B.客户端基本功能
首先建立一个通用地址结构server_addr,用于接收命令行中输入的服务器的IP地址和端口号,利用intmain()函数接受运行时要求在在运行文件后输入服务器IP和port,以此初始化地址结构,否则报错。
然后建立套接字接口,并将此套接口和基本输入套接口加入到套接口集合client_set中,向服务器发送连接请求,建立TCP连接,然后调用非阻塞的select函数,并判读select的EINTR和EAGIN等错误,系统在该函数上直到超时(设定为1s)或者本地套接口或基本套接接口的缓存中有数据可读。
如果本地套接口sockfd在client_set中,则直接接收消息并在屏幕上显示。
如果是基本输入套接口在client_set中,说明键盘上有要发送的消息输入,则将数据发送到服务器,另判读输入是否为“quit”,是的话关闭套接字,提示退出,并且服务器端之后将接收到该套接字0字符,则关闭与该客户端对应的套接字。
C.扩展功能:
1.聊天记录查询功能:
首先,服务器在要转发群聊消息前,先将每句消息前加入“clientnsaid”存入log_buf中,这个部分在群聊功能中实现。
当服务器端接收到的消息用strncasecmp()函数判断与“checkchatlog”前13位相符时,调用write()函数,将log_buf中的内容写到发送请求的客户端句柄fd中,返回聊天记录。
功能框图:
2.私聊功能:
见同组成员杨处
3.多聊功能:
在服务器端收到要转发的消息时,先用strncasecmp()函数判断消息前16个字符是否为“sendtoclients”(包括clients之后的空格),若是则判读”sendtoclients”后有几个连续的数字,并以空格结尾,记录为n,若其中有提出请求的客户端句柄号,则返回错误提示,不发送该消息,若不以空格结尾则判读为格式错误,给提出请求的客户端发送提示,不发送聊天信息,若不为”sendtoclients”则判断是否为其他功能,否则视为群聊,存入聊天记录中。
功能框图:
4.功能提示模块:
见同组队员报告
5.报错功能:
在运行的过程中如果出现新建socket,connect、write、read等不成功则会调用errexit函数报错退出;
私聊过程中目标客户端判断是否为本机套接字句柄或者非在线用户句柄则报错,但不退出。
多聊过程中输入格式不正确非“sendtoclientsabc…”格式则报错不发送消息,目标中含本机或者非在线用户都会提示错误,不发送消息。
客户端select函数的EINTR/EAGAIN报错。
总扩展功能框图:
D.编程中调用的头文件
代码中用到的函数及结构体及其对应的头文件:
Stdarg.h:
va_listva_startva_end
string.h:
vfprintf()
sys/socket.h:
StructsockaddrStructsockadd_in
socket()bind()listen()accept()connect()send()recv()
stdlib.hatoi()
string.hvoidbzero()
unistd.hselect()
sys/time.htimeval
string.h:
strerro
errno.h:
interrno
stdlib.hgcvt()
netinet/in.hhtons()
E.方案选择
聊天记录功能,仅针对于群聊情况下,在服务器端建立buf存储。
可以考虑改在客户端实现,记录所有客户端接受到信息,并建立记录文件与之对应。
群聊功能的实现,最初的方案是检测“sendtoclients”后各位若为数字,则发送,以空格结尾终止检测。
边检测边发送,就会导致数字后不是以空格结尾的情况或者连续数字中插入非数字的情况,也被视为合法的群聊选择,使先检测到的数字对应的客户端接收到消息。
改进方案,先检测后发送。
先完整检测客户端消息的输入前端是否符合”sendtoclients+空格+多数字+空格”的格式,若非则给出相关提示,若是则记录数字个数,重新读取数字及目标套接字号,对其发送消息。
关于客户端的退出功能,起初仅考虑到在客户端关闭套接字,而服务器端对应的套接字未关闭,致使服务器写套接字失败而退出,发现后使服务器的读套接字时为零,判断为客户端关闭,则服务器关闭相应套接字。
F.经验教训
在代码运行测试阶段会发现许多在算法设计及编写代码时未考虑到的问题,说明我们对于算法设计还不够扎实,对应用户需求还不够了解,不能全面的想到各种用户非法格式的输入,以及用户需求,应该做好充分的前期需求分析和算法设计,减少代码的多次修改。
VI.调试结果与改进方案
A.运行说明
1.PC机上:
编译产生运行文件:
Server:
gcc-Wall-g-oserverserver.c
Client:
gcc-Wall-g-oclientclient.c
运行服务器端可执行文件:
在运行文件所在目录中输入./server[],[]中输入运行端口,若不输入则采用默认端口8000监听,例如./server8003即运行服务器程序并以8003端口监听。
运行客户端可执行文件:
在运行文件所在目录中输入./client127.0.0.18000以8000端口与本机通信,IP和端口号可替换为其他主机IP及端口号。
发送消息:
然后可以在各client界面敲入想发送的信息
1).群聊(广播式):
若非如下几种特殊输入格式即为群聊,所有在线用户皆可接受到,并存入聊天记录中,其他聊天模式不存入聊天记录中。
2).查询聊天记录:
在client界面键入:
checkchatlog
3).单聊(私聊):
在client界面键入:
sendtoclientN(注意N前有空格)、(N为您想私聊对象(client)的socket句柄号,在群聊的过程中可以看到大家的句柄号)、(注意不能发给自己,否则会报错)
4).多聊:
在client界面键入:
sendtoclientsabc(注意abc前有空格)、(abc为您想多聊对象(各client)的socket句柄号,在群聊的过程中可以看到大家的句柄号)、(注意不能发给自己,否则会报错)
5).退出:
在client界面键入:
quit即可使此client退出聊天室,其他人继续聊天
2.ARM上:
服务器运行在ARM上,客户端运行在PC机上:
编译产生运行文件:
Server:
arm-linux-gcc-Wall-g-oserver.armserver.c
Client:
gcc-Wall-g-oclientclient.c
挂载:
将PC机上的nfs文件夹挂载到ARM上:
在超级终端中键入:
#mount-tnfs192.168.0.10:
/home/arm/nfs/tmp
其他同PC机上
B.运行结果及说明:
运行服务器端,三个客户端连接上服务器,截图如下:
客户端与服务器建立连接后,返回句柄值,显示运行提示,如下:
群聊功能,三个客户端登陆时,直接发送消息,一个发送消息其他两个客户端同时收到:
私聊功能,客户端6输入“sendtoclient4Iamno6”给客户端4发送消息,而同时在线的客户端5收不到消息:
多聊功能,登陆四个客户端,客户端5输入“sendtoclients46helloerverone”发送消息给客户端4和6,客户端7不能收到消息:
私聊和多聊时不能选定自己为目标,否则会出现警告:
输入“checkchatlog”查看消息,截图如下:
在客户端中输入“quit”,客户端退出,其他客户端接收到“client7sayquit”,重新登陆,获得原先的句柄号:
给不在线客户端发送私聊消息的警告提示:
C.改进方案:
1、用户名:
现有功能是使用服务器端接受端口的socket句柄号作为客户端的标志,并不够友好。
可以考虑服务器端建立二维数组,在客户端运行一开始时要求输入用户名,存入服务器接受socket号对应的二维数组元素中,在需要时返回用户名,而不返回句柄好。
2、在线查询:
查询fd_setready的值即可只相应的在线用户,返回所以对应的用户名。
3、透明传输:
虽然设定了特殊的字符串作为功能调用指令,但是同时也意味着这些字符串无法作为正常通信消息,可以考虑用键盘上的按键作为功能的调用键,例如按下“Esc”实现客户端退出功能。
4、聊天记录中不包括私聊和多聊的内容,这样可以保护隐私(可改进成可以查询私人聊天记录和多人聊天记录,这样对应更多个buf去对应)
5、健壮性:
程序在某些时候还可能出现bug,服务器退出现象。
VII.实验总结
此次嵌入式linux实验选择的是网络聊天程序,一开始先复习了课件的知识,到图书馆借阅相关书籍,上网查找了相关资料,利用select()方式实现了服务器与客户端的非阻塞式的通信,之后使用遍历服务器接受端口的办法实现了群聊的基本功能,在实习了基本功能后,我们从使用通信工具的角度,依次添加了返回客户端标志功能、客户端退出、聊天记录功能、单聊功能、多聊功能。
在实现中我们先是一起设计讨论了各个模块的实现算法,之后分工编写代码,在编写代码的过程中很好的巩固和提高了C语言编程的能力。
在代码编写后运行中又发现Bug,然后调整算法从新修改代码的过程也有发生,例如单聊功能的实现,一开始并没想到发送给本客户端的情况,在运行测试过程才得以发现。
虽然,这是一个两个人的小程序,但是也可以感受到,注释与编程规范化的重要性,若过于随意组员阅读困难,自己重读、调试时也不轻松。
此次实验程序还有许多待改进的地方如用户名注册、登陆等功能由于时间不足而未实现。
还有一个特别遗憾的就是因为选择的是网络编程模块,几乎没有接触到试验箱的硬件部分,只是用来串口控制、网口通信,软件本身与PC机下linux编程没有区别,没能接触到硬件部分是一种遗憾。
总之,此次实验让我掌握了利用linux下socket通信的方法、提高了算法设计和代码编写能力及代码规范化意识。
VIII.参考文献
[1]孙琼图书馆目录[M].北京:
人民邮电出版社,2006.7
[2]鄢舒嵌入式Linux软件课程设计课件武汉.华中科技大学电信系