基于TCPIP的网络文字聊天程序设计.docx
《基于TCPIP的网络文字聊天程序设计.docx》由会员分享,可在线阅读,更多相关《基于TCPIP的网络文字聊天程序设计.docx(27页珍藏版)》请在冰点文库上搜索。
基于TCPIP的网络文字聊天程序设计
网络编程课程设计
题目
基于TCP/IP的网络文字聊天程序设计
系、部:
计信学院
学生姓名:
学号:
专业:
网络工程
班级:
网络1102班
指导教师:
王新祥
完成时间:
2013-12-18
前言
Socket协议:
socket的英文原义是“孔”或“插座”。
在这里作为4BDSUNIX的进程通信机制,取后一种意思。
socket非常类似于电话插座。
以一个国家级电话网为例。
电话的通话双方相当于相互通信的2个进程,区号是它的网络地址;区内一个单位的交换机相当于一台主机,主机分配给每个用户的局内号码相当于socket号。
任何用户在通话之前,首先要占有一部电话机,相当于申请一个socket;同时要知道对方的号码,相当于对方有一个固定的socket。
然后向对方拨号呼叫,相当于发出连接请求(假如对方不在同一区内,还要拨对方区号,相当于给出网络地址)。
对方假如在场并空闲(相当于通信的另一主机开机且可以接受连接请求),拿起电话话筒,双方就可以正式通话,相当于连接成功。
双方通话的过程,是一方向电话机发出信号和对方从电话机接收信号的过程,相当于向socket发送数据和从socket接收数据。
通话结束后,一方挂起电话机相当于关闭socket,撤消连接。
在电话系统中,一般用户只能感受到本地电话机和对方电话号码的存在,建立通话的过程,话音传输的过程以及整个电话系统的技术细节对他都是透明的,这也与socket机制非常相似。
socket利用网间网通信设施实现进程通信,但它对通信设施的细节毫不关心,只要通信设施能提供足够的通信能力,它就满足了。
至此,我们对socket进行了直观的描述。
抽象出来,socket实质上提供了进程通信的端点。
进程通信之前,双方首先必须各自创建一个端点,否则是没有办法建立联系并相互通信的。
正如打电话之前,双方必须各自拥有一台电话机一样。
在网间网内部,每一个socket用一个半相关描述:
(协议,本地地址,本地端口)
一个完整的socket有一个本地唯一的socket号,由操作系统分配。
最重要的是,socket是面向客户/服务器模型而设计的,针对客户和服务器程序提供不同的socket系统调用。
客户随机申请一个socket(相当于一个想打电话的人可以在任何一台入网电话上拨号呼叫),系统为之分配一个socket号;服务器拥有全局公认的socket,任何客户都可以向它发出连接请求和信息请求(相当于一个被呼叫的电话拥有一个呼叫方知道的电话号码)。
一、课程设计任务书
(一)设计题目
基于TCP/IP的网络文字聊天程序设计
(二)设计要求
1、对设计方法的要求
使用VisualC++6.0开发出在Windows控制台或图形界面下运行的程序。
2、对设计内容的要求
实现网络文字聊天程序的服务器端。
实现网络文字聊天程序的客户端。
主程序的结构和流程。
程序运行过程的截图。
网络文字聊天程序的实现原理。
网络文字聊天程序实现代码的分析。
3、对课程设计说明书的要求
①设计思路与开发过程。
②对主要代码段要有较详细的注释。
③对本次设计的评价、设计的收获与建议。
4、说明书为打印件
(三)设计完成后要上交的材料
1、将说明书和源程序文件与可执行文件,一并存入光盘并上交(以班为单位,每个学生一个文件夹,文件夹名为“学号_姓名”,这个目录下存放工程文件夹与说明书的Word2003文档)。
2、设计说明书一份(必须用A4纸打印,不得少于20页)。
二、课程设计内容
(一)设计功能:
实现网络文字聊天程序的基本功能。
主要包括:
1.TCP聊天服务器程序
2.TCP聊天客户端程序
3.TCP聊天室程序
(二)程序设计流程图
1、功能模块图
2、TCP网络聊天服务器流程图
3、TCP网络聊天客户端流程图
4、网络聊天室程序
(三)程序设计原理
聊天室原理:
1、客户选择聊天的对象,将信息发送给服务器,然后服务器对这个信息进行判断,找到对应的套接字发送,而不发给其他用户。
2、客户选择聊天的对象,将信息发送给服务器,服务器不管这个消息,只认为是普通的信息,逐次发给每一个用户,有客户程序来判断,如果是自己的消息就显示出来;如果不是,则不加理睬。
3、类似QQ那样的,当客户要求跟某人说话的时候,重新开启一个客户模式,实现点对点的通信。
4、进入服务器界面和客户端,表明服务器和客户端连接正常。
如果服务器地址或者端口号码输入错误,将不能连接到服务器,系统显示不能连接并且询问是否重新登陆。
此时须重新设定以上两项内容然后登陆。
这个程序中对发送的信息判断比较多,信息的格式定义也比较多。
虽然不难,都是一些字符串的操作,但是比较复杂。
(四)程序主要代码
TCP聊天客户端程序代码:
#include"stdafx.h"
#include"CSocketcli.h"
#include"CSocketcliDlg.h"
#include
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
classCAboutDlg:
publicCDialog
{public:
CAboutDlg();
//{{AFX_DATA(CAboutDlg)
enum{IDD=IDD_ABOUTBOX};
//}}AFX_DATA
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtualvoidDoDataExchange(CDataExchange*pDX);//}}AFX_VIRTUAL
//Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg:
:
CAboutDlg():
CDialog(CAboutDlg:
:
IDD)
{//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
voidCAboutDlg:
:
DoDataExchange(CDataExchange*pDX)
{CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//Nomessagehandlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CCSocketcliDlg:
:
CCSocketcliDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CCSocketcliDlg:
:
IDD,pParent)
{//{{AFX_DATA_INIT(CCSocketcliDlg)
//}}AFX_DATA_INIT
m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
voidCCSocketcliDlg:
:
DoDataExchange(CDataExchange*pDX)
{CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCSocketcliDlg)
DDX_Control(pDX,IDC_BUTTON3,m_disconnect);
DDX_Control(pDX,IDC_BUTTON2,m_connect);
DDX_Control(pDX,IDC_EDIT2,m_edit2);
DDX_Control(pDX,IDC_LIST1,m_list);
DDX_Control(pDX,IDC_BUTTON1,m_button1);
DDX_Control(pDX,IDC_EDIT1,m_edit);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCSocketcliDlg,CDialog)
//{{AFX_MSG_MAP(CCSocketcliDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1,OnButton1)
ON_BN_CLICKED(IDC_BUTTON2,OnButton2)
ON_BN_CLICKED(IDC_BUTTON3,OnDisconnect)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOLCCSocketcliDlg:
:
OnInitDialog()
{CDialog:
:
OnInitDialog();
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty())
{pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon
m_edit.SetLimitText(99);
m_list.InsertColumn(0,"消息");
m_list.SetColumnWidth(0,435);
m_button1.EnableWindow(FALSE);
m_disconnect.EnableWindow(FALSE);
m_edit2.SetWindowText("192.168.0.3");
count=0;
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
}
voidCCSocketcliDlg:
:
OnSysCommand(UINTnID,LPARAMlParam)
{if((nID&0xFFF0)==IDM_ABOUTBOX)
{CAboutDlgdlgAbout;
dlgAbout.DoModal();
}
else
{CDialog:
:
OnSysCommand(nID,lParam);
}
}
voidCCSocketcliDlg:
:
OnPaint()
{if(IsIconic())
{CPaintDCdc(this);//devicecontextforpainting
SendMessage(WM_ICONERASEBKGND,(WPARAM)dc.GetSafeHdc(),0);
//Centericoninclientrectangle
intcxIcon=GetSystemMetrics(SM_CXICON);
intcyIcon=GetSystemMetrics(SM_CYICON);
CRectrect;
GetClientRect(&rect);
intx=(rect.Width()-cxIcon+1)/2;
inty=(rect.Height()-cyIcon+1)/2;
//Drawtheicon
dc.DrawIcon(x,y,m_hIcon);
}
else{CDialog:
:
OnPaint();
}
}
HCURSORCCSocketcliDlg:
:
OnQueryDragIcon()
{return(HCURSOR)m_hIcon;
}
voidCCSocketcliDlg:
:
OnOK()
{//CDialog:
:
OnOK();
}
//发送信息
voidCCSocketcliDlg:
:
OnButton1()
{charbuff[100];
CSizesize;
size.cx=0;
size.cy=30;
//获得发送信息
m_edit.GetWindowText(buff,99);
m_edit.SetWindowText("");
m_list.InsertItem(count++,buff);
m_list.Scroll(size);
//发送数据
send(clisock,buff,100,0);
}
//线程
UINTthread(LPVOIDv)
{charbuff[100];
chararray[25][30]=
{"155.245.160.151",
"155.245.160.152",
"155.245.160.153",
"155.245.160.154",
"155.245.160.155",
"155.245.160.156",
"155.245.160.157",
"155.245.160.158",
"155.245.160.159",
"155.245.160.160",
"155.245.160.161",
"155.245.160.162",
"155.245.160.163",
"155.245.160.164",
"155.245.160.165",
"155.245.160.166",
"155.245.160.167",
"155.245.160.168",
"155.245.160.169",
"155.245.160.170",
"155.245.160.171",
"155.245.160.172",
"155.245.160.173",
"155.245.160.174",
"155.245.160.175"};
CSizesize;
size.cx=0;
size.cy=30;
ints=1,addcount=0;
CCSocketcliDlg*dlg=(CCSocketcliDlg*)AfxGetApp()->GetMainWnd();
dlg->m_connect.EnableWindow(FALSE);
dlg->m_disconnect.EnableWindow(TRUE);
//连接到服务器
while(connect(dlg->clisock,(sockaddr*)&(dlg->cli),sizeof(dlg->cli))&&dlg->ee!
=0)
{dlg->m_edit.SetWindowText("等待.....");
//空循环
for(inti=0;i<=65000;i++)
for(intj=0;j<=200;j++);
if(addcount==25)
addcount=0;
dlg->cli.sin_addr.s_addr=inet_addr(array[addcount++]);
}if(dlg->ee==1)
dlg->m_list.InsertItem(dlg->count++,"连接成功");
dlg->m_button1.EnableWindow(TRUE);
dlg->SetForegroundWindow();
//循环获得数据
while(s!
=SOCKET_ERROR&&dlg->ee!
=0)
{//调用recv函数接收数据
s=recv(dlg->clisock,buff,100,0);
dlg->SetForegroundWindow();
if(s!
=SOCKET_ERROR&&dlg->ee!
=0)
dlg->m_list.InsertItem(dlg->count++,buff);
dlg->m_list.Scroll(size);
}
//发送断开命令
send(dlg->clisock,"Disconnected",100,0);
dlg->m_button1.EnableWindow(FALSE);
dlg->m_connect.EnableWindow(TRUE);
dlg->m_disconnect.EnableWindow(FALSE);
closesocket(dlg->clisock);
AfxEndThread(0);
return0;
}
CCSocketcliDlg:
:
~CCSocketcliDlg()
{send(clisock,"Disconnected",100,0);
}
//连接服务器
voidCCSocketcliDlg:
:
OnButton2()
{charipaddress[35];
m_edit2.GetWindowText(ipaddress,30);
cli.sin_addr.s_addr=inet_addr(ipaddress);
cli.sin_family=AF_INET;
cli.sin_port=5000;//htons(5000);
//创建socket
clisock=socket(AF_INET,SOCK_STREAM,0);
ee=1;
//启动线程
AfxBeginThread(thread,0);
}
voidCCSocketcliDlg:
:
OnDisconnect()
{ee=0;
closesocket(clisock);
}
TCP聊天服务器程序主要代码:
#include"stdafx.h"
#include"CSocket.h"
#include"CSocketDlg.h"
#include
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
classCAboutDlg:
publicCDialog
{public:
CAboutDlg();
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg:
:
CAboutDlg():
CDialog(CAboutDlg:
:
IDD)
voidCAboutDlg:
:
DoDataExchange(CDataExchange*pDX)
{CDialog:
:
DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)
END_MESSAGE_MAP()
CCSocketDlg:
:
CCSocketDlg(CWnd*pParent)
:
CDialog(CCSocketDlg:
:
IDD,pParent)
{m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
voidCCSocketDlg:
:
DoDataExchange(CDataExchange*pDX)
{CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCSocketDlg)
DDX_Control(pDX,IDC_BUTTON1,m_button);
DDX_Control(pDX,IDC_LIST1,m_list);
DDX_Control(pDX,IDC_EDIT1,m_edit);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCSocketDlg,CDialog)
//{{AFX_MSG_MAP(CCSocketDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1,OnButton1)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//初始化对话框
BOOLCCSocketDlg:
:
OnInitDialog()
{CDialog:
:
OnInitDialog();
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon
count=0;
m_list.InsertColumn(0,"消息");
m_list.SetColumnWidth(0,435);
m_edit.SetLimitText(99);
for(inti=0;i<50;i++)
msgsock[i]=NULL;
//设定地址
serv.sin_addr.s_addr=htonl(INADDR_ANY);
serv.sin_family=AF_INET;
serv.sin_port=5000;//htons(5000);
addlen=sizeof(serv