计算机网络课程设计-- 用WINSOCK实现聊天室的VC++程序设计.doc_第1页
计算机网络课程设计-- 用WINSOCK实现聊天室的VC++程序设计.doc_第2页
计算机网络课程设计-- 用WINSOCK实现聊天室的VC++程序设计.doc_第3页
计算机网络课程设计-- 用WINSOCK实现聊天室的VC++程序设计.doc_第4页
计算机网络课程设计-- 用WINSOCK实现聊天室的VC++程序设计.doc_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

课程设计 计算机网络学生姓名: 学 号:10225509312 专业班级:计算机2093班指导老师: 用winsock实现聊天室的vc+程序设计摘 要:winsock 是在windows进行网络通信编程的api接口,也是windws网络编程的事实标准。在网络编程中最常用的方案便是客户机/服务器模型。本文提出了在客户机/服务器模型下用winsock实现internet中常见的聊天室软件的方案。关键词:套接字,winsock,客户机/服务器,网络编程一:socket简介80年代初,美国政府的高级研究工程机构(arpa)给加利福尼亚大学berkeley分校提供了资金,让他们在unix操作系统下实现tcp/ip协议。在这个项目中,研究人员为tcp/ip网络通信开发了一个api(应用程序接口)。这个api称为socket接口(套接字)。今天,socket接口是tcp/ip网络最为通用的api,也是在internet上进行应用开发最为通用的api。90年代初,由microsoft联合了其他几家公司共同制定了一套windows下的网络编程接口,即windowssockets规范。它是berkeleysockets的重要扩充,主要是增加了一些异步函数,并增加了符合windows消息驱动特性的网络事件异步选择机制。windowssockets规范是一套开放的、支持多种协议的windows下的网络编程接口。从1991年的1.0版到1995年的2.0.8版,经过不断完善并在intel、microsoft、sun、sgi、informix、novell等公司的全力支持下,已成为windows网络编程的事实上的标准。目前,在实际应用中的windowssokcets规范主要有1.1版和2.0版。两者的最重要区别是1.1版只支持tcp/ip协议,而2.0版可以支持多协议。2.0版有良好的向后兼容性,任何使用1.1版的源代码,二进制文件,应用程序都可以不加修改地在2.0规范下使用。socket实际在计算机中提供了一个通信端口,可以通过这个端口与任何一个具有socket接口的计算机通信。应用程序在网络上传输,接收的信息都通过这个socket接口来实现。在应用开发中就像使用文件句柄一样,可以对socket句柄进行读,写操作。二:基于windows socket的应用开发介绍。在windows95/98,windowsnt进行winsock开发使用的编程语言有很多,vc+,java,delphi,vb等。其中vc时使用最普遍,和winsock结合最紧密的。并且vc+对原来的windowssockets库函数进行了一系列封装,继而产生了casynsocket、csocket、csocketfile等类,它们封装着有关socket的各种功能,是编程变得更加简单。但如果你是一个winsock编程的初学者,那么建议你在一开始还是学习winsock最基本的api函数进行编程,这样可以大大加深对winsock的了解,对将来很有好处。在vc中进行winsock的api编程开发,需要使用到下面三个文件:1 winsock.h: 这是winsock api的头文件。2 wsock32.lib: winsock api连接库文件。在使用中,一点要把它作为项目的非缺省的连接库包含到项目文件中去。3 winsock.dll: winsock的动态连接库,位于windows的安装目录下。可以看到,winsock。dll位于tcp/ip协议栈和应用程序之间。也就是说,winsock管理与tcp/ip协议的接口。在一开始winsock的应有开发时,你不必对tcp/ip协议有很深刻的了解。但是,如果想成为一个为网络编程的高手,就一定要对下层了解得十分清楚。在网络编程中最常用的方案便是客户机/服务器模型。在这种方案中客户应用程序向服务器程序请求服务。一个服务程序通常在一个众所周知的地址监听对服务的请求,也就是说,服务进程一直处于休眠状态,直到一个客户对这个服务的地址提出了连接请求。在这个时刻,服务程序被“惊醒”并且为客户提供服务对客户的请求作出适当的反应。虽然基于连接协议(流套接字)的服务是设计客户机/服务器应用程序时的标准,但有些服务也是可以通过无连接协议(数据报套接字)提供的。一般在使用中,面向连接协议的socket编程模型应用最为广泛,因为面向连接协议提供了一系列的数据纠错功能,可以保证在网络上传输的数据及时、无误地到达对方。 总的来说,使用socket接口(面向连接或无连接)进行网络通信时,必须按下面简单的四步进行处理:1、程序必须建立一个 socket。2、程序必须按要求配置此socket。也就是说,程序要么将此socket连接到远方的主机上,要么给此socket指定一个本地协议端口。3、程序必须按要求通过此socket发送和接收数据。4、程序必须关闭此socket。三:winsock api主要函数简介作者利用winsock api 编写了一个具有聊天室功能的应用程序,可用作学习 winsock 程序设计的参照。winsock api 包括很多函数,但其中最常用,包括在文章所附源程序中的有:注:只是有关函数的简要说明,具体规则、说明请参见vc+帮助和winsock规范。1、wsastartup():连结应用程序与 windows sockets dll 的第一个函数。说明: 此函数是应用程序调用 windows sockets dll函数中的第一个,也唯有此函数呼叫成功後,才可以再调用其他 windows sockets dll 的函数。2、wsacleanup():结束 windows sockets dll 的使用。说明: 当应用程序不再需要使用 windows sockets dll时,须调用此函数来注销使用,以便释放其占用的资源。3、 socket():建立socket。说明: 此函数用来建立一 socket 描述字,并为此 socket 建立其所使用的资源。4、 closesocket():关闭某一socket。说明: 此一函数是用来关闭某一 socket。5、 bind():将一本地地址与一个socket描述字连接在一起。说明:此函数在服务程序上使用,是调用监听函数listen()必须要调用的函数。6、 listen():设定 socket 为监听状态,准备被连接。说明: 此函数在服务程序上使用,来设定 socket 进入监听状态,并设定最多可有多少个在未真正完成连接前的客户端的连接要求。(目前最大值限制为 5, 最小值为1)7、 accept():接受某一socket的连接要求,以完成面向连接的客户端 socket 的连接请求。说明: 服务端应用程序调用此函数来接受客户端socket 连接请求,accept() 函数的返回值为一新的 socket,新 socket 就可用来在服务端和客户端之间的信息传递接收,而原来 socket 仍然可以接收其他客户端的连接要求。8、 connect():要求连接某一socket到指定的网络上服务端。说明: 此函数用在客户端,用来向服务端要求建立连接。当连接建立完成後,客户端即可利用此 socket 来与服务端进行信息传递。9、 recv():从面向连接的 socket 接收信息。说明: 此函数用来从面向连接的 socket 接收信息。10、send():使用面向连接的 socket 发送信息。说明: 此函数用来从面向连接的 socket 发送信息。11、wsaasyncselect():要求某一 socket 有事件 (event) 发生时通知使用者。说明: 此函数用来请求windows sockets dll 为窗口句柄发一条消息无论它何时检测到由levent参数指明的网络事件。要发送的消息由wmsg参数标明.被通知的套接口由s标识。本函数自动将套接口设置为非阻塞模式。levent参数由下表中列出的值组成。值 意义fd_read 欲接收读准备好的通知。fd_write 欲接收写准备好的通知。fd_oob 欲接收带边数据到达的通知。fd_accept 欲接收将要连接的通知。fd_connect 欲接收已连接好的通知。fd_close 欲接收套接口关闭的通知。这个函数可以认为是 winsock api 中最为重要的一个函数。要想使用好这个函数,你必须对 windows 编程的事件驱动和消息传递有很清楚的了解。四:聊天室应用程序的设计说明:软件功能:internet上可以提供一种叫irc 的服务。使用者通过客户端的程序登录到irc服务器上,就可以与登录在同一irc服务器上的客户进行交谈,这也就是平常所说的聊天室。在这里,给出了一个在运行tcp/ip协议的网络上实现irc服务的程序。软件使用说明:首先,在一台计算机上运行服务端程序,然后就可以在同一网络的其他计算机上运行客户端程序,登录到服务器上,各个客户之间就可以聊天了。软件设计要点:1、服务端核心代码在 cserverviwe 类中,有一个 socket 变量 m_hserversocket 和 socket 数组 m_aclientsocketmaxclient(maxclient:所定义的接收连接客户的最大数目),m_hserversocket 用来在指定的端口(1000)进行侦听,如果有客户端请求连接,则在 m_aclientsocket 数组中查找一个空 socket,将客户端的地址赋予此 socket。每当一个 clientsocket 接收到信息,都将会向窗口发一条消息。程序接收到这个消息后,再把接收到的信息发送给每一个 clientsocket。2、客户端客户端比较简单,核心代码在 cclientdlg 类中。只有一个 socket 变量 m_hsocket,与服务端进行连接。连接建立好后,通过此 socket 发送和接收信息。为了简化设计,用户名在客户端控制,服务器端只进行简单的接收信息和“广播”此信息,不进行名字校验,也就是说,可以有同名客户登录到服务端。这个程序设计虽然简单,但是已经具备了聊天室的最基本的功能。程序在vc+ 6.0 下编译通过,在使用 tcp/ip 协议的 windows 95/98 对等局域网 和使用 tcp/ip 协议的 windows nt 局域网上运行良好。- 程序代码:import java.applet.*; import java.awt.*; import java.io.*; import .*; import java.awt.event.*; public class chatclient extends applet protected boolean loggedin;/登入状态 protected frame cp;/聊天室框架 protected static int portnum=7777; /缺省端口号7777 protected int port;/实际端口号 protected socket sock; protected bufferedreader is;/用于从sock读取数据的bufferedreader protected printwriter pw;/用于向sock写入数据的printwriter protected textfield tf;/用于输入的textfield protected textarea ta;/用于显示对话的textarea protected button lib;/登入按钮 protected button lob;/登出的按钮 final static string title =chatroom applet; protected string paintmessage;/发表的消息 public chatparameter chat; public void init() paintmessage=正在生成聊天窗口; repaint(); cp=new frame(title); cp.setlayout(new borderlayout(); string portnum=getparameter(port);/呢个参数勿太明 port=portnum; if (portnum!=null) /书上是portnum=null,十分有问题 port=integer.parseint(portnum); /cgi ta=new textarea(14,80); ta.seteditable(false);/read only attribute ta.setfont(new font(monospaced,font.plain,11); cp.add(borderlayout.north,ta); panel p=new panel(); button b; /for login button p.add(lib=new button(login); lib.setenabled(true); lib.requestfocus(); lib.addactionlistener(new actionlistener() public void actionperformed(actionevent e) login(); lib.setenabled(false); lob.setenabled(true); tf.requestfocus();/将键盘输入锁定再右边的文本框中 ); /for logout button p.add(lob=new button (logout); lob.setenabled(false); lob.addactionlistener(new actionlistener() public void actionperformed(actionevent e) logout(); lib.setenabled(true); lob.setenabled(false); lib.requestfocus(); ); p.add(new label (输入消息:); tf=new textfield(40); tf.addactionlistener(new actionlistener() public void actionperformed(actionevent e) if(loggedin) /pw.println(chat.cmd_bcast+tf.gettext();/chat.cmd.是咩野来? int j=tf.gettext().indexof(:); if(j0) pw.println(chat.cmd_mesg+tf.gettext(); else pw.println(chat.cmd_bcast+tf.gettext(); tf.settext();/勿使用flush()? ); p.add(tf); cp.add(borderlayout.south,p); cp.addwindowlistener(new windowadapter() public void windowclosing(windowevent e) /如果执行了setvisible或者dispose,关闭窗口 chatclient.this.cp.setvisible(false); chatclient.this.cp.dispose(); logout(); ); cp.pack();/勿明白有咩用? /将frame cp放在中间 dimension us=cp.getsize(), them=toolkit.getdefaulttoolkit().getscreensize(); int newx=(them.width-us.width)/2; int newy=(them.height-us.height)/2; cp.setlocation(newx,newy); cp.setvisible(true); paintmessage=window should now be visible; repaint(); /登录聊天室 public void login() if(loggedin) return; try sock=new socket(getcodebase().gethost(),port); is=new bufferedreader(new inputstreamreader(sock.getinputstream(); pw=new printwriter(sock.getoutputstream(),true); catch(ioexception e) showstatus(cant get socket: +e); cp.add(new label(cant get socket: +e); return; /构造并且启动读入器,从服务器读取数据,输出到文本框中 /这里,长成一个线程来避免锁住资源(lockups) new thread (new runnable() public void run() string line; try while(loggedin &(line=is.readline()!=null) ta.appendtext(line+n); catch(ioexception e) showstatus(我的天啊,掉线了也!); return; ).start(); /假定登录(其实只是打印相关信息,并没有真正登录) / pw.println(chat.cmd_login+appletuser); pw.println(chat.cmd_login+appletuser); loggedin =true; /模仿退出的代码 public void logout() if(!loggedin) return; loggedin=false; try if(sock!=null) sock.close(); catch(ioexception ign) / 异常处理哦 /没有设置stop的方法,即使从浏览器跳到另外一个网页的时候 /聊天程序还可以继续运行 public void paint(graphics g) dimension d=getsize(); int h=d.height; int w=d.width; g.fillrect(0,0,w,2); g.setcolor(color.black); g.drawstring(paintmessage,10,(h/2)-5); 聊天室服务器端 import .*; import java.io.*; import java.util.*; public class chatserver /聊天室管理员id protected final static string chatmaster_id=chatmaster; /系统信息的分隔符 protected final static string sep=: ; /服务器的socket protected serversocket servsock; /当前客户端列表 protected arraylist clients; /调试标记 protected boolean debug=false; public chatparameter chat; /主方法构造一个chatserver,没有返回值 public static void main(string argv) system.out.println(chat server0.1 starting); chatserver w=new chatserver(); w.runserver(); system.out.println(*error* chat server0.1 quitting); /构造和运行一个聊天服务 chatserver() chat=new chatparameter(); clients=new arraylist(); try servsock=new serversocket(7777);/实有问题拉,不过可能是他自己定义既一个class. system.out.println(chat server0.1 listening on port:+7777); catch(exception e) log(io exception in chatserver.); system.exit(0); public void runserver() try while(true) socket us=servsock.accept(); string hostname=us.getinetaddress().gethostname(); system.out.println(accpeted from +hostname); /一个处理的线程 chathandler cl=new chathandler(us,hostname); synchronized(clients) clients.add(cl); cl.start(); if(clients.size()=1) cl.send(chatmaster_id,welcome!you are the first one here); else cl.send(chatmaster_id,welcome!you are the latest of+ clients.size()+ users.); catch(exception e) log(io exception in runserver:+e); system.exit(0); protected void log(string s) system.out.println(s); /处理会话的内部的类 protected class chathandler extends thread /客户端scoket protected socket clientsock; /读取socket的bufferedreader protected bufferedreader is ; /在socket 上发送信息行的printwriter protected printwriter pw; /客户端出主机 protected string clientip; /句柄 protected string login; public chathandler (socket sock,string clnt)throws ioexception clientsock=sock; clientip=clnt; is=new bufferedreader( new inputstreamreader(sock.getinputstream(); pw=new printwriter (sock.getoutputstream(),true); /每一个chathandler是一个线程,下面的是他的run()方法 /用于处理会话 public void run() string line; try while(line=is.readline()!=null) char c=line.charat(0);/我顶你老母啊 ,果只chat.cmd咩xx冇定义 扑啊/! line=line.substring(1); switch(c) /case chat.cmd_login: case l: if(!chat.isvalidloginname(line) send(chatmaster_id,login+line+invalid); log(login invalid from:+clientip); continue; login=line; broadcast(chatmaster_id,login+ joins us,for a total of+ clients.size()+ users); break; / case chat.cmd_mesg: case m: if(login=null) send(chatmaster_id,please login first); continue; int where =line.indexof(chat.separator); string recip=line.substring(0,where); string mesg=line.substring (where+1); log(mesg: +login+-+recip+: +mesg); chathandler cl=lookup(recip); if(cl=null) psend(chatmaster_id,recip+not logged in.); else cl.psend(login,mesg); break; /case chat.cmd_quit: case q: broadcast(chatmaster_id,goodbye to +login+clientip); close(); return;/chathandler结束 / case chat.cmd_bcast: case b: if(login!=null) broadcast(login,line); else log(b); else if(clients.size()=1) chathandler last=(chathandler)clients.get(0); last.send(chatmaster_id,hey,you are talking to yourself again); else broadcast(chatmaster_id,there are now+clients.size()+ users); protected void close() if(clientsock=null) log(close when not open); return; tr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论