linux 操作实现即时通讯程序
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
“3+1”实训
学院计算机工程学院
姓名何健
班级 11计4ZS 学号 11141407 指导教师李红卫
2014年 12月12日
基于Linux的即时通程序的实现
一、摘要
作为一种便捷的网络通讯技术,即时通讯软件已经越来越深入人心,应用范围从单纯的网络聊天工具变成工作生活所不可或缺的信息交流平台。正因为它的重要性, 找出其存在的问题和其自身的局限性,显得尤为迫切。现实的情况是IM 软件基本上都集中在MS Windows平台,很少考虑Linux用户的需求,这给IM应用的普及带来了不便。因此如能将即时通讯软件移植到Linux操作系统,不仅弥补Linux系统下应用软件匮乏的现状,同时对Linux系统和即时通讯软件普及也有重要意义。
通过分析和研究即时通讯模型,并对当前几种流行的即时通讯协议的对比,本文采用基于UDP的TCP协议,客户端与服务器采用短连接的通信方式,客户端与客户端采用端对端的通信方式。在系统的具体实现中,客户端设计出相关界面并对相应界面实现了登陆、注册、发送消息、查询信息、添加好友、文件发送等功能;服务器端响应客户端的命令请求并用多线程方案解决了服务器的并发。
关键字:即时通信,Linux ,客户端,服务器
二、需求分析
随着中小型企事业的不断发展,在企业内部实现局域网通信是必不可少的。局域网聊天工具就是一个非常好的局域网通信软件,它可以在职工不移动位置的情况下进行在线聊天、文件传递。这样,可以大大提高企业的工作效率,便于企业内部职员的交流。根据用户对聊天工具的要求,可分为以下几点:
(1) 操作简单方便、界面简洁美观;
(2) 可以在局域网实现文字和文件的传输; (3) 可以实现用户的注册、登录和注销;
(4) 程序启动之后就能看到当前哪些机器在线,哪些可以与之进行对等通信。可以实现局域网聊天;
(5) 一旦有某个网内的机器上线了,要有即时通知,并能及时更新用户界面中的用户列表;
(6) 当单击用户列表项的时候,直接在聊天对话框聊天,发送聊天信息;
(7) 当有远程用户向本机发送文件的时候,弹出一个消息提示,用户可选择接收或者拒绝;
(8) 文件传输过程中,应该有当前传输状态提示,并作为当前网络状态的一种反馈;
(9) 为用户提供一个简单的聊天记录保存功能。
三、概要设计
客户端之间采用的通信协议主要是UDP。一个客户端要想和另一个客户端
进行通信必须要知道对方的ip地址和端口号。因此每个客户端在登录之后必须向服务器发送自己的ip和端口号,服务器将返回其在线好友的ip和端口号,然后服务器还会通过UDP向其好友群发其ip和端口号,在线的好友收到该消息后就会将其保存在自己的在校好友列表里。这样有了好友的ip和端口号后就可以直接与其进行通信了,这里的客户端也要兼有服务端的职责,可以将它看作P2P (端到端,peer to peer)。
为了保证数据的可靠性,对于连续发送大量有序的数据包,采用UDP协议并不保险,因此在必要的时候,也必须采用TCP协议来支持数据的稳定和可靠性。在iQQ里,由于发送文件时时会连续发送大量的数据,因此此时最好使用TCP协议进行数据通信。
四、相关代码
//--------------------------------server.c--------------------------------------------------
//包含工程所需的头文件
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PERM S_IRUSR|S_IWUSR
#define MYPORT 3490 //宏定义定义通信端口
#define BACKLOG 10 //宏定义,定义服务程序可以连接的最大客户数量
#define WELCOME "|----------Welcome to the chat room! ----------|" //宏定义,当客户端连接服务端时,想客户发送此欢迎字符串
//转换函数,将int类型转换成char *类型
void itoa(int i,char*string)
{
int power,j;
j=i;
for(power=1;j>=10;j/=10)
power*=10;
for(;power>0;power/=10)
{
*string++='0'+i/power;
i%=power;
}
*string='\0';
}
//得到当前系统时间
void get_cur_time(char * time_str)
{
time_t timep;
struct tm *p_curtime;
char *time_tmp;
time_tmp=(char *)malloc(2);
memset(time_tmp,0,2);
memset(time_str,0,20);
time(&timep);
p_curtime = localtime(&timep);
strcat(time_str," (");
itoa(p_curtime->tm_hour,time_tmp);
strcat(time_str,time_tmp);
strcat(time_str,":");
itoa(p_curtime->tm_min,time_tmp);
strcat(time_str,time_tmp);
strcat(time_str,":");
itoa(p_curtime->tm_sec,time_tmp);
strcat(time_str,time_tmp);
strcat(time_str,")");
free(time_tmp);
}
//创建共享存储区
key_t shm_create()
{
key_t shmid;
//shmid = shmget(IPC_PRIVATE,1024,PERM);
if((shmid = shmget(IPC_PRIVATE,1024,PERM)) == -1)
{
fprintf(stderr,"Create Share Memory Error:%s\n\a",strerror(errno)); exit(1);
}
return shmid;
}
//端口绑定函数,创建套接字,并绑定到指定端口