网络编程聊天程序设计文档.docx

上传人:b****2 文档编号:2627736 上传时间:2023-05-04 格式:DOCX 页数:46 大小:280.82KB
下载 相关 举报
网络编程聊天程序设计文档.docx_第1页
第1页 / 共46页
网络编程聊天程序设计文档.docx_第2页
第2页 / 共46页
网络编程聊天程序设计文档.docx_第3页
第3页 / 共46页
网络编程聊天程序设计文档.docx_第4页
第4页 / 共46页
网络编程聊天程序设计文档.docx_第5页
第5页 / 共46页
网络编程聊天程序设计文档.docx_第6页
第6页 / 共46页
网络编程聊天程序设计文档.docx_第7页
第7页 / 共46页
网络编程聊天程序设计文档.docx_第8页
第8页 / 共46页
网络编程聊天程序设计文档.docx_第9页
第9页 / 共46页
网络编程聊天程序设计文档.docx_第10页
第10页 / 共46页
网络编程聊天程序设计文档.docx_第11页
第11页 / 共46页
网络编程聊天程序设计文档.docx_第12页
第12页 / 共46页
网络编程聊天程序设计文档.docx_第13页
第13页 / 共46页
网络编程聊天程序设计文档.docx_第14页
第14页 / 共46页
网络编程聊天程序设计文档.docx_第15页
第15页 / 共46页
网络编程聊天程序设计文档.docx_第16页
第16页 / 共46页
网络编程聊天程序设计文档.docx_第17页
第17页 / 共46页
网络编程聊天程序设计文档.docx_第18页
第18页 / 共46页
网络编程聊天程序设计文档.docx_第19页
第19页 / 共46页
网络编程聊天程序设计文档.docx_第20页
第20页 / 共46页
亲,该文档总共46页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

网络编程聊天程序设计文档.docx

《网络编程聊天程序设计文档.docx》由会员分享,可在线阅读,更多相关《网络编程聊天程序设计文档.docx(46页珍藏版)》请在冰点文库上搜索。

网络编程聊天程序设计文档.docx

网络编程聊天程序设计文档

此文档为网络编程课程设计文档。

课程设计题目:

网络编程——聊天程序

程序运行环境:

UbuntuLinux

编程语言:

C语言

使用图形界面技术:

GTK+2.0

本人是大学本科生,所学知识有限,在此班门弄虎了,希望与大家在技术上多多交流。

此文所有权归本人所有,所以请勿抄袭。

网络编程

聊天程序设计报告

学院:

计算机与电子信息学院

专业名称:

网络工程

姓名:

网名:

书箱子

时间:

2011年1月

 

聊天程序设计任务书

1.设计题目

自己设计应用层协议,实现聊天程序,要求能够实现服务器能够同时处理多个客户的连接请求,实现客户端通过服务器的转发通信。

2.实验设计

2.1实验环境

1)虚拟机:

OracleVMVirtualBox

2)操作系统:

Ubuntu-10.10-desktop

2.2通信功能分析

实现聊天程序,并要考虑服务器能够同时处理多个客户的连接请求,实现客户端通过服务器的转发通信。

则通信过程分析如下:

服务器端:

1)建立socket绑定监听端口;

2)等待客户端的连接;

3)当客户与服务器建立连接后,服务器记录客户所有信息,如ID号;

4)当客户消息到达服务器后,服务器分析客户信息:

a.若为转发消息,根据消息格式提供的转发ID号,服务器立即查找转发列表,转发消息,若查找后发现需要转发的客户ID不存在则返回错误信息给原客户,提示不存在要发送的客户端ID号;

b.若为询问消息,服务器返回当前登录到服务器的所有客户的ID号;

c.若为退出消息,服务器清楚当前客户的所有信息,更新客户列表;

5)以上2-4步都是随时进行的:

a.任何新进客户端都能随时连接服务器;

b.任何以连接客户端都能发送消息,并且服务器能同时处理多个同时到来的消息,实现并发的处理客户端消息。

6)当服务器停止工作时,关闭监听套接字。

客户端:

1)建立连接到服务器的socket;

2)发送登录信息,信息中需要包含自身的ID号,使服务器能识别本机;

3)使用信号机制,随时能接收服务器传来的消息,不阻塞,及时的显示到来信息,并记录到来信息,以方便用户查看聊天记录;

4)能随时向服务器发送消息,有三种消息:

a.询问消息,询问服务器当前已连接到服务器的客户列表;

b.转发消息,告知服务器需要转发的ID号和信息,通过服务器进行聊天;

c.退出消息,告知服务器本客户端要退出聊天;

5)要获取当前以登录服务器的客户列表,则会发送询问消息,得到返回结果后更新本地的用户登录列表;

6)当想退出时,向服务器端发送退出消息后,关闭套接字,关闭程序。

2.3设计协议

通过以上服务器与客户端功能的分析,要完成以上功能,需要设计一个通信协议。

1)通信消息协议格式

协议格式中需要包含的信息有:

用户的ID号、接收者的ID号、退出标记、查询标记、转发标记、信息内容。

所以构造如下:

a.协议使用基于文本的格式:

chat#####

b.相应使用到的结构体:

structChatMsg{

charID[20];//自己的ID号

chartoID[20];//需要发送的ID号

boolisQuit;//发送的是退出消息时为true

boolisInquiry;//发送的是询问消息时为true

charmsg[128];//需要发送的信息内容

};

c.字符串“chat”,是魔术字符串,因为不能确定消息在传送过程中是否会出现问题,所以使用一个字符串测试消息的正确性;

d.字符串“”,表明发送消息的客户端自己的ID号;

e.字符串“”,当要转发消息时,此字符串表明要转发的目的客户端ID号;

f.字符串“”,当被标识为‘q’时,表示退出,标识为‘i’时,表示询问,标识为‘u’时,表示默认转发,‘q’与‘i’可以同时放在一起,因为如果是询问消息,则不可能是退出消息,反之如果是退出消息就不可能是询问消息;

g.字符串“”,表示要发送的信息内容;

h.字符串协议中,使用‘#’字符表示分隔符,用以分隔各个字段。

2)通信消息协议实现

通过此协议格式,可以实现三种消息的通信(如客户ID:

wang,消息发送到ID:

zhao):

a.询问消息:

chat#wang#server#i##

b.转发消息:

chat#wang#zhao#u#hello.#

c.退出消息:

chat#wang#server#q##

消息协议的实现使用Coder.c实现消息的编码,此文件中有如下两个函数:

/*实现消息的编码,输入消息ChatMsg结构体,返回消息字符串与长度*/

size_tEncode(structChatMsg*cmsg,uint8_t*outBuf,size_tbufSize);

/*实现消息的解码,输入消息字符串,返回消息ChatMsg结构体与消息长度*/

intDecode(uint8_t*inBuf,size_tmSize,structChatMsg*cmsg);

2.4程序所使用技术

根据对通信功能的分析,需要用到相应的技术解决通信过程中需要完成的功能,经过分析,,发现需要完成的主要功能有四项:

1)基本消息传输;2)不阻塞接收消息;3)服务器并发处理多客户消息;4)程序界面易操作性。

本实验对应不同的功能,提供不同的技术解决方案,各项功能实现技术描述如下。

2.4.1基本消息传输

1)采用UDP协议传送消息,采用此技术传送消息主要考虑到其简单性,容易在程序中实现,并且不需要考虑面向连接所要解决的问题,如何建立与何时断开连接都是在用TCP时需要考虑的问题,还有就是消息的成帧,在TCP中需要考虑成帧的问题,在TCP中有两种解决办法,一直是以定界符的方式,另一种是以固定长度的方法,而在UDP中并不需要考虑这个问题,因为使用UDP传送时,消息的边界已经是确定的了,而无需再去指定,所以使用UDP只需要考虑如何编码协议即可,但采用UDP也有很大的问题,那就是UDP本身固有的缺点,消息传送的不安全性,无重传的机制,无法知道消息是否到达。

2)UDP技术的实现:

a.服务器端建立UDPsocket并绑定监听socket:

(核心代码)

server_socket=socket(servAddr->ai_family,servAddr->ai_socktype,

servAddr->ai_protocol);

bind(server_socket,servAddr->ai_addr,servAddr->ai_addrlen);

b.客户端建立UDPsocket并通过指定端口连接到服务器:

(核心代码)

my_socket=socket(servAddr->ai_family,servAddr->ai_socktype,

servAddr->ai_protocol);

2.4.2不阻塞接收消息

1)采用信号量机制,实现不阻塞接收消息,当有I/O信号到来的时候才调用相应的函数处理到来的消息,这样可以让出CPU去执行其他的代码,提高了程序的执行效率,这样作的好处显而易见。

在此程序中使用了GTK+2.0的图形界面编程技术,所以在实现上与书本所介绍的方法并不一致。

2)服务器端与客户端都实现了采用信号量机制的消息接收方式:

a.服务器端采用信号量机制接收信息:

(核心代码)

/*监听以创建的socket端口是否有输入信号准备好;

*若信号已准备好则调用线程处理函数ThreadHandle()处理到来消息*/

gdk_input_add(server_socket,GDK_INPUT_READ,ThreadHandle,NULL);

b.客户端采用信号量机制接收信息:

(核心代码)

/*监听以创建的socket端口是否有输入信号准备好;

*若信号已准备好则调用函数SIGReceive()处理到来消息*/

gdk_input_add(my_socket,GDK_INPUT_READ,SIGReceive,NULL);

2.4.3服务器并发处理多客户消息

1)服务器需要并发的处理多个客户同时发送信息的要求,考虑使用多线程技术,实现并发的处理信息,因为没有使用TCP协议来实现此程序,所以不能使用accpet函数接收客户端的连接,并单独的为每位客户端创建一个线程来处理消息的转发。

但在UDP的实现中一样需要用到线程技术来解决并发的处理客户消息,因为不同客户的消息可能会同时到达,若不采用多线程技术,则会出现如下这样的情况:

先前到达的消息还没处理完又有新的消息到达,而新到达的消息则会等待,若还有其它消息的到达,也都会等待,当客户端的数量达到一定程度时,如不使用线程技术处理到来的消息,则会使整个通信过程产生很大的时延,有可能还会使服务器瘫痪(如一个消息在处理过程中出错,程序暂停执行)。

所以考虑使用多线程技术实现客户端消息的并发处理。

2)服务器端多线程技术的实现,因为使用了GTK+2.0图形界面编程,所以在实现多线程上与课本上的实现不太相同:

(核心代码)

/*首先使用信号量技术,监听以创建的socket端口是否有输入信号准备好;

*若信号已准备好则调用线程处理函数“ThreadHandle()“处理到来消息*/

gdk_input_add(server_socket,GDK_INPUT_READ,ThreadHandle,NULL);

/*以下为线程处理函数,当有I/O信号到来时会调用此函数创建一个线程,

*实现消息的并发处理。

此线程完成对每个客户消息的处理,调HandleClient()函数*/

voidThreadHandle(){

g_thread_create((GThreadFunc)HandleClient,NULL,FALSE,NULL);

}

2.4.4程序界面易操作性

考虑到此实验实现起来的复杂性,并不是太困难,所以考虑使用图形界面的方式呈现此聊天程序,使程序有更好的用户体验,而不是面对一个由一堆字符组成的终端界面。

同时因为个人喜好问题,所以选择了Linux下的图形界面设计,采用GTK+进行图形界面设计,此处就不对GTK的编程细节进行描述,在实验运行结果图中会展示使用GTK+所创建的图形界面。

3、实验运行结果图

3.1实验准备

1)服务器监听端口号:

3693;服务器地址:

127.0.0.1、192.168.10.3、(在/etc/hosts中设置,因为程序使用了getaddrinfo()函数可以识别此地址)

2)客户端需要获得:

服务器的端口号与IP地址;客户端准备自己的ID号唯一识别一台主机,此实验中开始三个客户端分别为:

wang1客户、wang2客户、wang3客户。

3)实验所用程序名:

服务器端为ServerWindow,客户端为ClientWindow

3.2实验拓扑图

3.3通信过程截图

1)点击“Start“按钮,启动服务器,监听3693端口

图1服务器端界面

2)客户wang1,启动客户端程序,输入服务器IP地址127.0.0.1,端口号3693,客户ID为wang1,点击”Connect”按钮连接服务器,连接成功后会弹出对话框,通知连接成功。

图2客户端界面,wang1客户

3)客户wang2,启动客户端程序,输入服务器地址,端口号3693,客户ID为wang2,点击”Connect”按钮连接服务器,连接成功后会弹出对话框,通知连接成功。

(如图3)

4)客户wang3,启动客户端程序,输入服务器地址192.168.10.3,端口号3693,客户ID为wang3,点击”Connect”按钮连接服务器,连接成功后会弹出对话框,通知连接成功。

(如图4)

图3wang2客户图4wang3客户

5)当三个客户端都连接上服务器后,服务器列表增加了三个客户信息,同时客户点击刷新按钮“Refreshonlineusers”时,会获取服务器当前以登录客户端的客户ID

 

6)wang2与wang3向wang1发送消息如图7图8

图7wang2向wang1发送消息图8wang3向wang1发送消息

7)wang1接收到wang2与wang3发来的消息,消息会直接显示,查看聊天记录使用按钮“front”与“next”,如图9图10

图9按front按钮查看wang2的消息图10按next按钮查看wang3的消息

8)wang1客户端向一个不存在的客户端(如wang4)发送信息时,服务器会返回消息提示不存在此客户,如图11图12

图11向不存在客户端(wang4)发信息图12服务器返回信息,提示wang4不在线

9)wang1点击按钮“Close”退出聊天室,服务器刷新客户列表去除wang1用户,同时使用wang2向wang1发送信息,提示wang1不在线,如图13图14

图13服务器列表中已没有wang1用户图14向wang1发送信息提示wang1不在线

10)测试结果显示,服务器和客户端能完成聊天任务,实验成功。

4、实验程序文件与源代码

4.1实验所使用的文件

1)服务器端使用文件:

ChatComponent.hCoder.cMessageDialog.cServerWindow.c

2)客户端使用文件:

ChatComponent.hCoder.cMessageDialog.cSendAndReceive.c

ClientWindow.c

3)各文件说明:

a.ChatComponent.h此头文件中包含有:

对应本程序协议的结构体,与功能函数的声明,客户端与服务器端的这个文件并不完全相同;

b.Coder.c编码文件,使用本程序设计的协议进行编码与解码;

c.MessageDialog.c消息提示组件,用于弹出提示对话框,因使用频繁所以单独写成文件;

d.ServerWindow.c服务器端文件,存放服务器端程序原代码;

e.SendAndReceive.c客户端使用的文件,使用此文件进行信息的发送与接收;

f.ClientWindow.c客户端文件,存放客户端程序源代码;

4)编译所使用的命令:

服务器端编译命令:

gcc`pkg-configgtk+-2.0--cflags--libsgthread-2.0`-std=gnu99-o

ServerWindowServerWindow.cChatComponent.hCoder.cMessageDialog.c

服务器端程序名:

ServerWindow

客户端编译命令:

gcc`pkg-config--cflags--libsgtk+-2.0`-std=gnu99-oClientWindow

ClientWindow.cChatComponent.hCoder.cSendAndReceive.cMessageDialog.c

客户端程序名:

ClientWindow

4.2实验文件源代码

1)ChatComponent.h客户端

#ifndefCHATCOMPONENT_H_

#defineCHATCOMPONENT_H_

#include

#include

#include

#include

#include

#include

#include

//最大发送字符

#defineMAXBUF256

//最大记录信息条数

#defineMAXMSGNUM30

//消息协议所对应的结构体

structChatMsg{

charID[20];//idfromself

chartoID[20];//idfromanother

boolisQuit;//telltheserverquit

boolisInquiry;//inquiryserveronlineusers

charmsg[128];//chatmessage

};

//聊天历史记录

structRecvMsg{

charfromID[20];

charmsg[128];

};

//记录聊天历史记录的队列,使用数字队列

structQueueIndex{

intfront;

intrear;

};

//对话框消息

intSystemInfo(char*from,char*msg);

//消息的编码与解码函数

size_tEncode(structChatMsg*cmsg,uint8_t*outBuf,size_tbufSize);

intDecode(uint8_t*inBuf,size_tmSize,structChatMsg*cmsg);

//方便客户端对消息的发送与接收

intSendMsg(structaddrinfo*servAddr,intsocket,structChatMsg*cmsg);

intReceiveMsg(structaddrinfo*servAddr,intsocket,structChatMsg*cmsg);

#endif//CHATCOMPONENT_H_

2)ChatComponent.h服务器端

#ifndefCHATCOMPONENT_H_

#defineCHATCOMPONENT_H_

#include

#include

#include

#include

#include

#include

#include

#include

//最大发送字符

#defineMAXBUF256

//最大连接客户数

#defineMAXCONNECT30

//消息协议所对应的结构体

structChatMsg{

charID[20];//idfromself

chartoID[20];//idfromanother

boolisQuit;//telltheserverquit

boolisInquiry;//inquiryserveronlineusers

charmsg[128];//chatmessage

};

//记录连接客户的信息

structRecordClient{

charclntID[20];

structsockaddr_storageclntAddr;

socklen_tclntAddrLen;

};

//对话框消息

intSystemInfo(char*from,char*msg);

//消息的编码与解码函数

size_tEncode(structChatMsg*cmsg,uint8_t*outBuf,size_tbufSize);

intDecode(uint8_t*inBuf,size_tmSize,structChatMsg*cmsg);

#endif//CHATCOMPONENT_H_

3)Coder.c

#include

#include

#include

#include

#include

#include"ChatComponent.h"

/*消息采用文本编码方式.

*文本编码格式:

"chat####"*/

staticconstchar*MAGIC="chat";

staticconstchar*QUIT="q";

staticconstchar*INQUIRY="i";

staticconstchar*DELIMSTR="#";

/*编码函数,输入消息结构体变量,返回字符串*/

size_tEncode(structChatMsg*cmsg,uint8_t*outBuf,size_tbufSize){

uint8_t*bufPtr=outBuf;

longsize=(size_t)bufSize;

intrv=snprintf((char*)bufPtr,size,"%s#%s#%s#%s#%s#",MAGIC,cmsg->ID,cmsg->toID,

(cmsg->isQuit?

QUIT:

(cmsg->isInquiry?

INQUIRY:

"u")),cmsg->msg);

bufPtr+=rv;

return(size_t)(bufPtr-outBuf);

}

/*解码函数,输入字符串,返回消息结构体变量*/

intDecode(uint8_t*inBuf,size_tmSize,structChatMsg*cmsg){

char*token;

token=strtok((char*)inBuf,DELIMSTR);

//Checkformagic

if(token==NULL||strcmp(token,MAGIC)!

=0)return-1;

//GetID

token=strtok(NULL,DELIMSTR);

if(token==NULL)return-1;

strcpy(cmsg->ID,token);

strcat(cmsg->ID,"\0");

//GettoID

token=strtok(NULL,DELIMSTR);

if(token==NULL)return-1;

strcpy(cmsg->toID,token);

strcat(cmsg->toID,"\0");

//GetisQuitorisInquiry

token=strtok(NULL,DELIMSTR);

if(token==NULL)return-1;

if(strcmp(token,QUIT)==0){

cmsg->isQuit=true;

cmsg->isInquiry=false;

}elseif(strcmp(token,INQUIRY)==0){

cmsg->isQuit=false;

cmsg->isInquiry=true;

}else{

cmsg->isQuit=false;

cms

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2