CSU计算机网络实验报告.docx
《CSU计算机网络实验报告.docx》由会员分享,可在线阅读,更多相关《CSU计算机网络实验报告.docx(27页珍藏版)》请在冰豆网上搜索。
CSU计算机网络实验报告
计算机网络实验报告
学号:
姓名:
班级:
学院:
信息科学与工程学院
指导老师:
实验一:
距离向量路由算法的实现
1.1实验目的
模拟距离向量路由算法的路由表交换过程,演示每轮交换后路由表的变化。
1.2实验内容
要求编程实现距离矢量路由算法的路由表交换过程,并动态演示每轮交换过后路由表的变化情况。
1.3实验原理
距离向量路由算法,使用这个算法的路由器必须掌握这个距离表(它是一个一维排列,即一个向量),它告诉在网络中每个节点的最远和最近距离。
在距离表中的这个信息是根据临近接点信息的改变而时时更新的。
表中数据的量和在网络中的所有的接点(除了它自己本身)是等同的。
这个表中的列代表直接和它相连的邻居,行代表在网络中的所有目的地。
每个数据包括传送数据包到每个在网上的目的地的路径和距离/时间在那个路径上来传输(我们叫这个为“成本”)。
这个在那个算法中的度量公式是跳跃的次数,等待时间,流出数据包的数量等等。
在距离向量路由算法中,相邻路由器之间周期性地相互交换各自的路由表备份。
当网络拓扑结构发生变化时,路由器之间也将及时地相互通知有关变更信息。
每个路由器维护了一张路由表,它以子网中的每个路由器为索引,并且每个路由器对应一个表项。
该表项包含两部分:
为了达到该目标路由器而使用的输出线路,以及到达该目标路由器的时间估计值或者距离估计值。
距离矢量路由算法在理论中可以工作,但在实践中有一个严重的缺陷:
虽然它总是能够达到正确的答案,但是它收敛到正确答案的速度非常慢,尤其是,它对于好消息的反应非常快,但是对于坏消息的反应非常迟缓。
1.4实验步骤
1.4.1编写程序
程序的源代码如下:
#include"stdio.h"
#include"stdlib.h"
#include"alloc.h"
#defineROUTNUM7
typedefstruct
{
intdis;
intfrom;
}RoutNode;
RoutNodedata[ROUTNUM][ROUTNUM];/*路由表*/
voidInitData(FILE*pfile);/*从数据文件读取数据,初始化路由表*/
voidOutputRoutData();/*输出所有的路由表*/
voidCommunication(intrecv,intsend);/*send点向recv点发送自己的路由表*/
voidExchange();/*所有节点进行一次数据交换,更新路由表*/
voidmain()
intstart,end,i,j;
FILE*pfile;
pfile=fopen("1.txt","r");
if(pfile==NULL)
printf("文件打开错误,按任意键退出.\n");
getch();
return;
}
else
InitData(pfile);
fclose(pfile);
printf("\n路由表初始:
\n");
for(i=0;i{printf("%c||",i+65);for(j=0;jif(data[i][j].dis>0)printf("<%c%d>",j+65,data[i][j].dis);printf("\n");}for(i=0;i{Exchange();}printf("\n路由表交换:\n");OutputRoutData();printf("输入起始路由节点(%d-%d):",0,ROUTNUM-1);scanf("%d",&start);printf("输入终点路由节点(%d-%d):",0,ROUTNUM-1);scanf("%d",&end);if(start==end||start<0||start>6||end<0||end>6){printf("\n输入错误,请按任意键退出\n");getch();return;}else{intcur=start;inttotal=0;if(data[start][end].dis<0){printf("没有路由路径发现!\n");getch();return;}/*endofif*/printf("%c->",cur+65);while(data[cur][end].from>=0){total+=data[cur][data[cur][end].from].dis;printf("%c->",data[cur][end].from+65);cur=data[cur][end].from;}/*endofwhile*/total+=data[cur][end].dis;printf("%c\n总的路由距离=%d",end+65,total);getch();return;}/*endofelse*/}voidInitData(FILE*pfile){charnum[10];inti=0;charc;intm,n;fseek(pfile,0,0);for(m=0;!feof(pfile)&&m<7;m++){for(n=0;!feof(pfile)&&n<7;n++){while(!feof(pfile)){c=fgetc(pfile);if(c==',')/*读完一个数字*/{num[i]='\0';data[m][n].dis=atoi(num);data[m][n].from=-1;i=0;break;}/*endofif*/elseif((c>='0'&&c<='9')||c=='-')/*如果读到数字或符号*/{num[i++]=c;}/*endofelseif*/}/*endofwhile*/}/*endoffor(n=0*/}/*endoffor(m=0*/}voidOutputRoutData(){inti,j;printf("");for(i=0;i{printf("%c",i+65);}printf("\n");for(i=0;i{printf("%c",i+65);for(j=0;j{if(data[i][j].dis<0)/*如果无路径*/printf("-");elseif(data[i][j].dis>=10)printf("%d",data[i][j].dis);elseprintf("%d",data[i][j].dis);if(data[i][j].from<0)/*如果未经过其它节点*/printf("-");elseprintf("%c",data[i][j].from+65);}/*endoffor(j=0*/printf("\n");}/*endoffor(i=0*/}voidCommunication(intrecv,intsend){inti;for(i=0;i{if(data[send][i].dis>0)/*如果send节点到i号节点有路线*/{if(data[recv][i].dis<0)/*如果recv到i号节点无路径*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}elseif(data[recv][i].dis>data[send][i].dis+data[recv][send].dis)/*如果现有路径比新路径远*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}}/*endofif*/}/*endoffor*/}voidExchange(){inti,j;for(i=0;i{for(j=0;j{if(data[i][j].dis>0)/*如果两个节点之间有路径*/{Communication(j,i);/*将i号节点的路由表发送给j号节点*/}/*endofif*/}/*endoffor(j=0*/}/*endoffor(i=0*/}1.4.2设计思路程序先定义了一个路由表——RoutNodedata[ROUTNUM][ROUTNUM],路由表的初始信息存储在文件中,程序运行是先调用函数InitData(FILE*pfile)从文件中读取路由表的初始信息,然后输出初始路由表的信息,Communication(intrecv,intsend)函数主要是向邻近节点发送自己的路由表信息,Exchange()函数则根据新路由表信息更新自己的路由表。当所有的路由表节点都更新一遍后,整个路由表更新完毕。1.5实验结果分析1.5.1结果截图1.5.2结果分析路由表初始信息从文件读取,根据距离向量路由算法系统自动完成路由表的更新操作,最后任意输入两个路由表接点,则可得出两接点之间的最短路径。1.6实验心得体会实验是对我们应用知识的考察,通过它我们能更加了解自己的能力。这次的实验是网络课实验中最简单的一次,但我做得一点都不好,还没有写软件的概念和思想,程序也写得不好,还没有再实验课上完成的,是后来到寝室才完成的,没有通过老师的检查,幸亏我们的老师心地善良,说不用检查也可以通过。这个程序只能实现主要的功能,没有界面,也没有什么操作,因能力有限,只能做到这个样子,还望老师见谅。有空的话我一定好好学习一种编程软件。实验二网络聊天窗口2.1实验目的1,进一步加深对网络底层数据传输过程的理解2,通过自己动手编写具体的代码,实现实验的要求,提高学生的编程能力3,熟悉socket编程接口,初步掌握用socket编程接口开发面向连接的网络应用程序的方法。4,熟悉socket编程接口,初步掌握用socket编程接口开发无连接的网络应用程序的方法。2.2实验原理为实现网络聊天的功能,采用WindowsSocket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。由于服务器端要保存用户信息,我们暂时利用文件保存来实现这一功能,这是为了保存较好的可移植性,在没装相应数据库的机子上也能顺利地运行。在客户端保存用户号码这一功能的实现中,采用了文件系统设计。在不同的客户间可以实现文件的传输,其原理与信息传送差不多,只不过传输的内容是文件字节流。 服务器及客户端的功能可划分为以下模块:客户端:1)登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。(由于本项目是作者09年时出于兴趣自己开始做的,所以界面中显示的是QQ2009)用用户名字登录。密码都默认为123其中,点击界面上的“注册新账号”会出现下图:在里面填写相应的名字和密码即可注册,当然服务器也要开启相应的端口,如下:2)界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。本界面中左边和右边都是截图所得,这些按钮没有实际功能,只为了模仿QQ。3)聊天功能:与好友聊天。本界面做的时候有点bug,就是聊天窗口中只有一个有个人形象展示,如上,在左边打开的窗口中没有,右边有。这一个bug有空会改过来的。4)发送文件:能发送任一文件,当然文件不能过大,否则可能会出问题。收到的图片可以正常打开5)信息提示:闪动托盘图标提示到来信息,并播放不同音乐来提示。6)其他:用户登陆成功,将保存其号码,以便下次登陆时,不必再输入而可以直接选择,显示登陆时间。服务器端:写上一个合适的端口后点击开启端口,就可以开启一个端口用来专门接收用户的连接。当有用户上线进,就会把相应的用户列在列表中。向各个客户端发布系统消息。接受来自客户端的各种信息并分别处理。1)登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就将在线用户发给该用户,并将该用户的状态发给各在线用户。同时在服务器端显示出来。2)聊天信息:转发给消息指定的用户。3)申请信息:自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。4)用户下线:将此用户下线消息发给各客户端,并改写用户在服务器端的状态。 2.3实验具体实现1、服务器端:服务器端启动时,先初始化服务端界面,之后开启一个端口用来监听客户端的连接:ChatServer.java文件里面:publicvoidsetUpServer(){try{System.out.println(port);//创建服务端套接字server=new.ServerSocket(port);MakeLog.writeLog("成功创建了一个套接字","ChatServer");//进入一个循环来等待客户端while(true){if(server!=null){.Socketclient=server.accept();//开一个线程ServerThreadnewThread=newServerThread(client);MakeLog.writeLog("已经创建一个线程连接.客户端地址:"+client.getRemoteSocketAddress(),"ChatServer");listSock.add(client);//启动线程newThread.start();}}}catch(Exceptione){e.printStackTrace();MakeLog.writeError(e.getMessage(),"ChatServer");}}然后,当有一个客户端连接上来的时候,就开启一个线程分配给该用户,用来管理该用户的连接及一些相关的操作。(其它知识点与本实验无关,这里就不再写了,下面看客户端)2、客户端:客户端一启动时,先构造出登陆界面,当点击登陆按钮时,先做一下简单的判断,看是否账号或密码为空,当它们都合法的时候就进入下一步:/***对登陆按钮作出回应*/publicvoidreact(){if(null!=tf_name.getText()||null!=tf_psw.getText()){name=tf_name.getText().trim();psw=tf_psw.getText().trim();System.out.println("name:"+name+"psw:"+psw);//创建一个连接,连接服务器connServer(serverIp,port);ClientMng.manage(client);//登陆if(ClientMng.logon(name,psw)){ClientThreadthreadCl=newClientThread();threadCl.start();}else{javax.swing.JOptionPane.showMessageDialog(jf,"登陆失败!!用户名已登陆或密码或用户名错误!");}}else{javax.swing.JOptionPane.showMessageDialog(null,"对不起,用户名和密码不能为空!!");kk=0;}jf.dispose();//最后把登陆界面关掉。}分析代码。先用客户端内置的预设的服务器地址和端口进行socket连接信尝试,连接成功时,客户端马上给服务器发送相关的用户名和密码,服务器验证通过的时候会向客户端返回一条确认信息,客户端如果接到该确认信息说明已经登陆成功了,他们就有了一个永久性的连接,直到其中的一方关闭连接为止。其实在这过程中,还有一些环节:/***登陆用的函数*@paramname:登陆用户名*@parampsw:登陆密码*@return:是否登陆成功,true登陆成功,false登陆失败*/publicstaticbooleanlogon(Stringname,Stringpsw){myName=name;StringnamePsw;if(clientSock!=null){namePsw=name+"#"+psw;sendMsg(namePsw,"system");//发送用户名和密码try{msg=readPackage();if(msg.equals("系统说:对不起,您的用户名可能为空或未注册或已登陆!!")){//javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),//"对不起,您的用户名可能为空或未注册或已登陆!!");returnfalse;}if(msg.equals("系统说:登陆失败!!密码错误!")){javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),"登陆失败!!密码错误!");returnfalse;}sendMsg("OK!","system");msg=readPackage();sendMsg("OK!","system");//接收服务器发过来的在线用户列表names=readPackage();//处理服务器刚发过来的在线用户列表if(names!=null&&!names.equals("")){String[]s=names.split("说:");String[]allName=s[1].split("#");for(inti=0;iif(!allName[i].equals("")&&allName[i]!=null&&!exists(allName[i])){listUser.add(allName[i]);}}}//发送一条消息告诉服务器,是否需要它发送分组信息过来if(needToSendTeamInfo()){sendMsg("发过来","system");//接收服务器发过来的分组信息并保存//msg=readPackage();SaveFileAfterRecievingTeamInfo();}else{sendMsg("不用发","system");initial();}}catch(Exceptionef){ef.printStackTrace();}returntrue;}returntrue;}当客户端发送了用户名和密码之后,如果收到的信息是:“对不起,您的用户名可能为空或未注册或已登陆!!”则说明重复登陆,登陆失败。如果收到的信息是:“登陆失败!!密码错误!”则说明是密码错误,当然也有可能是不存在这个用户。收到的信息如果是其它的情况,则登陆成功,这时,双方还会再各发条“OK”信息来确认双方的连接并协调步伐。之后,客户端会判断本地是否已经有相关的列表信息,如果有,则会直接读取本地好友列表信息,如果没有的话,会请求服务器发送相关的好友列表。收到好友列表后,再解析,并构建成一棵树,显示在界面的列表项中。客户端有一个工具类,里面有一个读取消息并分解消息的方法:/***按协议来读数据,包括XX说:*@return:读包结果*@throwsIOException*/publicstaticStringreadPackage()throwsIOException{//开始读数据if(dins!
printf("%c||",i+65);
for(j=0;jif(data[i][j].dis>0)printf("<%c%d>",j+65,data[i][j].dis);printf("\n");}for(i=0;i{Exchange();}printf("\n路由表交换:\n");OutputRoutData();printf("输入起始路由节点(%d-%d):",0,ROUTNUM-1);scanf("%d",&start);printf("输入终点路由节点(%d-%d):",0,ROUTNUM-1);scanf("%d",&end);if(start==end||start<0||start>6||end<0||end>6){printf("\n输入错误,请按任意键退出\n");getch();return;}else{intcur=start;inttotal=0;if(data[start][end].dis<0){printf("没有路由路径发现!\n");getch();return;}/*endofif*/printf("%c->",cur+65);while(data[cur][end].from>=0){total+=data[cur][data[cur][end].from].dis;printf("%c->",data[cur][end].from+65);cur=data[cur][end].from;}/*endofwhile*/total+=data[cur][end].dis;printf("%c\n总的路由距离=%d",end+65,total);getch();return;}/*endofelse*/}voidInitData(FILE*pfile){charnum[10];inti=0;charc;intm,n;fseek(pfile,0,0);for(m=0;!feof(pfile)&&m<7;m++){for(n=0;!feof(pfile)&&n<7;n++){while(!feof(pfile)){c=fgetc(pfile);if(c==',')/*读完一个数字*/{num[i]='\0';data[m][n].dis=atoi(num);data[m][n].from=-1;i=0;break;}/*endofif*/elseif((c>='0'&&c<='9')||c=='-')/*如果读到数字或符号*/{num[i++]=c;}/*endofelseif*/}/*endofwhile*/}/*endoffor(n=0*/}/*endoffor(m=0*/}voidOutputRoutData(){inti,j;printf("");for(i=0;i{printf("%c",i+65);}printf("\n");for(i=0;i{printf("%c",i+65);for(j=0;j{if(data[i][j].dis<0)/*如果无路径*/printf("-");elseif(data[i][j].dis>=10)printf("%d",data[i][j].dis);elseprintf("%d",data[i][j].dis);if(data[i][j].from<0)/*如果未经过其它节点*/printf("-");elseprintf("%c",data[i][j].from+65);}/*endoffor(j=0*/printf("\n");}/*endoffor(i=0*/}voidCommunication(intrecv,intsend){inti;for(i=0;i{if(data[send][i].dis>0)/*如果send节点到i号节点有路线*/{if(data[recv][i].dis<0)/*如果recv到i号节点无路径*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}elseif(data[recv][i].dis>data[send][i].dis+data[recv][send].dis)/*如果现有路径比新路径远*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}}/*endofif*/}/*endoffor*/}voidExchange(){inti,j;for(i=0;i{for(j=0;j{if(data[i][j].dis>0)/*如果两个节点之间有路径*/{Communication(j,i);/*将i号节点的路由表发送给j号节点*/}/*endofif*/}/*endoffor(j=0*/}/*endoffor(i=0*/}1.4.2设计思路程序先定义了一个路由表——RoutNodedata[ROUTNUM][ROUTNUM],路由表的初始信息存储在文件中,程序运行是先调用函数InitData(FILE*pfile)从文件中读取路由表的初始信息,然后输出初始路由表的信息,Communication(intrecv,intsend)函数主要是向邻近节点发送自己的路由表信息,Exchange()函数则根据新路由表信息更新自己的路由表。当所有的路由表节点都更新一遍后,整个路由表更新完毕。1.5实验结果分析1.5.1结果截图1.5.2结果分析路由表初始信息从文件读取,根据距离向量路由算法系统自动完成路由表的更新操作,最后任意输入两个路由表接点,则可得出两接点之间的最短路径。1.6实验心得体会实验是对我们应用知识的考察,通过它我们能更加了解自己的能力。这次的实验是网络课实验中最简单的一次,但我做得一点都不好,还没有写软件的概念和思想,程序也写得不好,还没有再实验课上完成的,是后来到寝室才完成的,没有通过老师的检查,幸亏我们的老师心地善良,说不用检查也可以通过。这个程序只能实现主要的功能,没有界面,也没有什么操作,因能力有限,只能做到这个样子,还望老师见谅。有空的话我一定好好学习一种编程软件。实验二网络聊天窗口2.1实验目的1,进一步加深对网络底层数据传输过程的理解2,通过自己动手编写具体的代码,实现实验的要求,提高学生的编程能力3,熟悉socket编程接口,初步掌握用socket编程接口开发面向连接的网络应用程序的方法。4,熟悉socket编程接口,初步掌握用socket编程接口开发无连接的网络应用程序的方法。2.2实验原理为实现网络聊天的功能,采用WindowsSocket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。由于服务器端要保存用户信息,我们暂时利用文件保存来实现这一功能,这是为了保存较好的可移植性,在没装相应数据库的机子上也能顺利地运行。在客户端保存用户号码这一功能的实现中,采用了文件系统设计。在不同的客户间可以实现文件的传输,其原理与信息传送差不多,只不过传输的内容是文件字节流。 服务器及客户端的功能可划分为以下模块:客户端:1)登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。(由于本项目是作者09年时出于兴趣自己开始做的,所以界面中显示的是QQ2009)用用户名字登录。密码都默认为123其中,点击界面上的“注册新账号”会出现下图:在里面填写相应的名字和密码即可注册,当然服务器也要开启相应的端口,如下:2)界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。本界面中左边和右边都是截图所得,这些按钮没有实际功能,只为了模仿QQ。3)聊天功能:与好友聊天。本界面做的时候有点bug,就是聊天窗口中只有一个有个人形象展示,如上,在左边打开的窗口中没有,右边有。这一个bug有空会改过来的。4)发送文件:能发送任一文件,当然文件不能过大,否则可能会出问题。收到的图片可以正常打开5)信息提示:闪动托盘图标提示到来信息,并播放不同音乐来提示。6)其他:用户登陆成功,将保存其号码,以便下次登陆时,不必再输入而可以直接选择,显示登陆时间。服务器端:写上一个合适的端口后点击开启端口,就可以开启一个端口用来专门接收用户的连接。当有用户上线进,就会把相应的用户列在列表中。向各个客户端发布系统消息。接受来自客户端的各种信息并分别处理。1)登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就将在线用户发给该用户,并将该用户的状态发给各在线用户。同时在服务器端显示出来。2)聊天信息:转发给消息指定的用户。3)申请信息:自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。4)用户下线:将此用户下线消息发给各客户端,并改写用户在服务器端的状态。 2.3实验具体实现1、服务器端:服务器端启动时,先初始化服务端界面,之后开启一个端口用来监听客户端的连接:ChatServer.java文件里面:publicvoidsetUpServer(){try{System.out.println(port);//创建服务端套接字server=new.ServerSocket(port);MakeLog.writeLog("成功创建了一个套接字","ChatServer");//进入一个循环来等待客户端while(true){if(server!=null){.Socketclient=server.accept();//开一个线程ServerThreadnewThread=newServerThread(client);MakeLog.writeLog("已经创建一个线程连接.客户端地址:"+client.getRemoteSocketAddress(),"ChatServer");listSock.add(client);//启动线程newThread.start();}}}catch(Exceptione){e.printStackTrace();MakeLog.writeError(e.getMessage(),"ChatServer");}}然后,当有一个客户端连接上来的时候,就开启一个线程分配给该用户,用来管理该用户的连接及一些相关的操作。(其它知识点与本实验无关,这里就不再写了,下面看客户端)2、客户端:客户端一启动时,先构造出登陆界面,当点击登陆按钮时,先做一下简单的判断,看是否账号或密码为空,当它们都合法的时候就进入下一步:/***对登陆按钮作出回应*/publicvoidreact(){if(null!=tf_name.getText()||null!=tf_psw.getText()){name=tf_name.getText().trim();psw=tf_psw.getText().trim();System.out.println("name:"+name+"psw:"+psw);//创建一个连接,连接服务器connServer(serverIp,port);ClientMng.manage(client);//登陆if(ClientMng.logon(name,psw)){ClientThreadthreadCl=newClientThread();threadCl.start();}else{javax.swing.JOptionPane.showMessageDialog(jf,"登陆失败!!用户名已登陆或密码或用户名错误!");}}else{javax.swing.JOptionPane.showMessageDialog(null,"对不起,用户名和密码不能为空!!");kk=0;}jf.dispose();//最后把登陆界面关掉。}分析代码。先用客户端内置的预设的服务器地址和端口进行socket连接信尝试,连接成功时,客户端马上给服务器发送相关的用户名和密码,服务器验证通过的时候会向客户端返回一条确认信息,客户端如果接到该确认信息说明已经登陆成功了,他们就有了一个永久性的连接,直到其中的一方关闭连接为止。其实在这过程中,还有一些环节:/***登陆用的函数*@paramname:登陆用户名*@parampsw:登陆密码*@return:是否登陆成功,true登陆成功,false登陆失败*/publicstaticbooleanlogon(Stringname,Stringpsw){myName=name;StringnamePsw;if(clientSock!=null){namePsw=name+"#"+psw;sendMsg(namePsw,"system");//发送用户名和密码try{msg=readPackage();if(msg.equals("系统说:对不起,您的用户名可能为空或未注册或已登陆!!")){//javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),//"对不起,您的用户名可能为空或未注册或已登陆!!");returnfalse;}if(msg.equals("系统说:登陆失败!!密码错误!")){javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),"登陆失败!!密码错误!");returnfalse;}sendMsg("OK!","system");msg=readPackage();sendMsg("OK!","system");//接收服务器发过来的在线用户列表names=readPackage();//处理服务器刚发过来的在线用户列表if(names!=null&&!names.equals("")){String[]s=names.split("说:");String[]allName=s[1].split("#");for(inti=0;iif(!allName[i].equals("")&&allName[i]!=null&&!exists(allName[i])){listUser.add(allName[i]);}}}//发送一条消息告诉服务器,是否需要它发送分组信息过来if(needToSendTeamInfo()){sendMsg("发过来","system");//接收服务器发过来的分组信息并保存//msg=readPackage();SaveFileAfterRecievingTeamInfo();}else{sendMsg("不用发","system");initial();}}catch(Exceptionef){ef.printStackTrace();}returntrue;}returntrue;}当客户端发送了用户名和密码之后,如果收到的信息是:“对不起,您的用户名可能为空或未注册或已登陆!!”则说明重复登陆,登陆失败。如果收到的信息是:“登陆失败!!密码错误!”则说明是密码错误,当然也有可能是不存在这个用户。收到的信息如果是其它的情况,则登陆成功,这时,双方还会再各发条“OK”信息来确认双方的连接并协调步伐。之后,客户端会判断本地是否已经有相关的列表信息,如果有,则会直接读取本地好友列表信息,如果没有的话,会请求服务器发送相关的好友列表。收到好友列表后,再解析,并构建成一棵树,显示在界面的列表项中。客户端有一个工具类,里面有一个读取消息并分解消息的方法:/***按协议来读数据,包括XX说:*@return:读包结果*@throwsIOException*/publicstaticStringreadPackage()throwsIOException{//开始读数据if(dins!
if(data[i][j].dis>0)
printf("<%c%d>",j+65,data[i][j].dis);
printf("\n");
for(i=0;i{Exchange();}printf("\n路由表交换:\n");OutputRoutData();printf("输入起始路由节点(%d-%d):",0,ROUTNUM-1);scanf("%d",&start);printf("输入终点路由节点(%d-%d):",0,ROUTNUM-1);scanf("%d",&end);if(start==end||start<0||start>6||end<0||end>6){printf("\n输入错误,请按任意键退出\n");getch();return;}else{intcur=start;inttotal=0;if(data[start][end].dis<0){printf("没有路由路径发现!\n");getch();return;}/*endofif*/printf("%c->",cur+65);while(data[cur][end].from>=0){total+=data[cur][data[cur][end].from].dis;printf("%c->",data[cur][end].from+65);cur=data[cur][end].from;}/*endofwhile*/total+=data[cur][end].dis;printf("%c\n总的路由距离=%d",end+65,total);getch();return;}/*endofelse*/}voidInitData(FILE*pfile){charnum[10];inti=0;charc;intm,n;fseek(pfile,0,0);for(m=0;!feof(pfile)&&m<7;m++){for(n=0;!feof(pfile)&&n<7;n++){while(!feof(pfile)){c=fgetc(pfile);if(c==',')/*读完一个数字*/{num[i]='\0';data[m][n].dis=atoi(num);data[m][n].from=-1;i=0;break;}/*endofif*/elseif((c>='0'&&c<='9')||c=='-')/*如果读到数字或符号*/{num[i++]=c;}/*endofelseif*/}/*endofwhile*/}/*endoffor(n=0*/}/*endoffor(m=0*/}voidOutputRoutData(){inti,j;printf("");for(i=0;i{printf("%c",i+65);}printf("\n");for(i=0;i{printf("%c",i+65);for(j=0;j{if(data[i][j].dis<0)/*如果无路径*/printf("-");elseif(data[i][j].dis>=10)printf("%d",data[i][j].dis);elseprintf("%d",data[i][j].dis);if(data[i][j].from<0)/*如果未经过其它节点*/printf("-");elseprintf("%c",data[i][j].from+65);}/*endoffor(j=0*/printf("\n");}/*endoffor(i=0*/}voidCommunication(intrecv,intsend){inti;for(i=0;i{if(data[send][i].dis>0)/*如果send节点到i号节点有路线*/{if(data[recv][i].dis<0)/*如果recv到i号节点无路径*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}elseif(data[recv][i].dis>data[send][i].dis+data[recv][send].dis)/*如果现有路径比新路径远*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}}/*endofif*/}/*endoffor*/}voidExchange(){inti,j;for(i=0;i{for(j=0;j{if(data[i][j].dis>0)/*如果两个节点之间有路径*/{Communication(j,i);/*将i号节点的路由表发送给j号节点*/}/*endofif*/}/*endoffor(j=0*/}/*endoffor(i=0*/}1.4.2设计思路程序先定义了一个路由表——RoutNodedata[ROUTNUM][ROUTNUM],路由表的初始信息存储在文件中,程序运行是先调用函数InitData(FILE*pfile)从文件中读取路由表的初始信息,然后输出初始路由表的信息,Communication(intrecv,intsend)函数主要是向邻近节点发送自己的路由表信息,Exchange()函数则根据新路由表信息更新自己的路由表。当所有的路由表节点都更新一遍后,整个路由表更新完毕。1.5实验结果分析1.5.1结果截图1.5.2结果分析路由表初始信息从文件读取,根据距离向量路由算法系统自动完成路由表的更新操作,最后任意输入两个路由表接点,则可得出两接点之间的最短路径。1.6实验心得体会实验是对我们应用知识的考察,通过它我们能更加了解自己的能力。这次的实验是网络课实验中最简单的一次,但我做得一点都不好,还没有写软件的概念和思想,程序也写得不好,还没有再实验课上完成的,是后来到寝室才完成的,没有通过老师的检查,幸亏我们的老师心地善良,说不用检查也可以通过。这个程序只能实现主要的功能,没有界面,也没有什么操作,因能力有限,只能做到这个样子,还望老师见谅。有空的话我一定好好学习一种编程软件。实验二网络聊天窗口2.1实验目的1,进一步加深对网络底层数据传输过程的理解2,通过自己动手编写具体的代码,实现实验的要求,提高学生的编程能力3,熟悉socket编程接口,初步掌握用socket编程接口开发面向连接的网络应用程序的方法。4,熟悉socket编程接口,初步掌握用socket编程接口开发无连接的网络应用程序的方法。2.2实验原理为实现网络聊天的功能,采用WindowsSocket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。由于服务器端要保存用户信息,我们暂时利用文件保存来实现这一功能,这是为了保存较好的可移植性,在没装相应数据库的机子上也能顺利地运行。在客户端保存用户号码这一功能的实现中,采用了文件系统设计。在不同的客户间可以实现文件的传输,其原理与信息传送差不多,只不过传输的内容是文件字节流。 服务器及客户端的功能可划分为以下模块:客户端:1)登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。(由于本项目是作者09年时出于兴趣自己开始做的,所以界面中显示的是QQ2009)用用户名字登录。密码都默认为123其中,点击界面上的“注册新账号”会出现下图:在里面填写相应的名字和密码即可注册,当然服务器也要开启相应的端口,如下:2)界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。本界面中左边和右边都是截图所得,这些按钮没有实际功能,只为了模仿QQ。3)聊天功能:与好友聊天。本界面做的时候有点bug,就是聊天窗口中只有一个有个人形象展示,如上,在左边打开的窗口中没有,右边有。这一个bug有空会改过来的。4)发送文件:能发送任一文件,当然文件不能过大,否则可能会出问题。收到的图片可以正常打开5)信息提示:闪动托盘图标提示到来信息,并播放不同音乐来提示。6)其他:用户登陆成功,将保存其号码,以便下次登陆时,不必再输入而可以直接选择,显示登陆时间。服务器端:写上一个合适的端口后点击开启端口,就可以开启一个端口用来专门接收用户的连接。当有用户上线进,就会把相应的用户列在列表中。向各个客户端发布系统消息。接受来自客户端的各种信息并分别处理。1)登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就将在线用户发给该用户,并将该用户的状态发给各在线用户。同时在服务器端显示出来。2)聊天信息:转发给消息指定的用户。3)申请信息:自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。4)用户下线:将此用户下线消息发给各客户端,并改写用户在服务器端的状态。 2.3实验具体实现1、服务器端:服务器端启动时,先初始化服务端界面,之后开启一个端口用来监听客户端的连接:ChatServer.java文件里面:publicvoidsetUpServer(){try{System.out.println(port);//创建服务端套接字server=new.ServerSocket(port);MakeLog.writeLog("成功创建了一个套接字","ChatServer");//进入一个循环来等待客户端while(true){if(server!=null){.Socketclient=server.accept();//开一个线程ServerThreadnewThread=newServerThread(client);MakeLog.writeLog("已经创建一个线程连接.客户端地址:"+client.getRemoteSocketAddress(),"ChatServer");listSock.add(client);//启动线程newThread.start();}}}catch(Exceptione){e.printStackTrace();MakeLog.writeError(e.getMessage(),"ChatServer");}}然后,当有一个客户端连接上来的时候,就开启一个线程分配给该用户,用来管理该用户的连接及一些相关的操作。(其它知识点与本实验无关,这里就不再写了,下面看客户端)2、客户端:客户端一启动时,先构造出登陆界面,当点击登陆按钮时,先做一下简单的判断,看是否账号或密码为空,当它们都合法的时候就进入下一步:/***对登陆按钮作出回应*/publicvoidreact(){if(null!=tf_name.getText()||null!=tf_psw.getText()){name=tf_name.getText().trim();psw=tf_psw.getText().trim();System.out.println("name:"+name+"psw:"+psw);//创建一个连接,连接服务器connServer(serverIp,port);ClientMng.manage(client);//登陆if(ClientMng.logon(name,psw)){ClientThreadthreadCl=newClientThread();threadCl.start();}else{javax.swing.JOptionPane.showMessageDialog(jf,"登陆失败!!用户名已登陆或密码或用户名错误!");}}else{javax.swing.JOptionPane.showMessageDialog(null,"对不起,用户名和密码不能为空!!");kk=0;}jf.dispose();//最后把登陆界面关掉。}分析代码。先用客户端内置的预设的服务器地址和端口进行socket连接信尝试,连接成功时,客户端马上给服务器发送相关的用户名和密码,服务器验证通过的时候会向客户端返回一条确认信息,客户端如果接到该确认信息说明已经登陆成功了,他们就有了一个永久性的连接,直到其中的一方关闭连接为止。其实在这过程中,还有一些环节:/***登陆用的函数*@paramname:登陆用户名*@parampsw:登陆密码*@return:是否登陆成功,true登陆成功,false登陆失败*/publicstaticbooleanlogon(Stringname,Stringpsw){myName=name;StringnamePsw;if(clientSock!=null){namePsw=name+"#"+psw;sendMsg(namePsw,"system");//发送用户名和密码try{msg=readPackage();if(msg.equals("系统说:对不起,您的用户名可能为空或未注册或已登陆!!")){//javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),//"对不起,您的用户名可能为空或未注册或已登陆!!");returnfalse;}if(msg.equals("系统说:登陆失败!!密码错误!")){javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),"登陆失败!!密码错误!");returnfalse;}sendMsg("OK!","system");msg=readPackage();sendMsg("OK!","system");//接收服务器发过来的在线用户列表names=readPackage();//处理服务器刚发过来的在线用户列表if(names!=null&&!names.equals("")){String[]s=names.split("说:");String[]allName=s[1].split("#");for(inti=0;iif(!allName[i].equals("")&&allName[i]!=null&&!exists(allName[i])){listUser.add(allName[i]);}}}//发送一条消息告诉服务器,是否需要它发送分组信息过来if(needToSendTeamInfo()){sendMsg("发过来","system");//接收服务器发过来的分组信息并保存//msg=readPackage();SaveFileAfterRecievingTeamInfo();}else{sendMsg("不用发","system");initial();}}catch(Exceptionef){ef.printStackTrace();}returntrue;}returntrue;}当客户端发送了用户名和密码之后,如果收到的信息是:“对不起,您的用户名可能为空或未注册或已登陆!!”则说明重复登陆,登陆失败。如果收到的信息是:“登陆失败!!密码错误!”则说明是密码错误,当然也有可能是不存在这个用户。收到的信息如果是其它的情况,则登陆成功,这时,双方还会再各发条“OK”信息来确认双方的连接并协调步伐。之后,客户端会判断本地是否已经有相关的列表信息,如果有,则会直接读取本地好友列表信息,如果没有的话,会请求服务器发送相关的好友列表。收到好友列表后,再解析,并构建成一棵树,显示在界面的列表项中。客户端有一个工具类,里面有一个读取消息并分解消息的方法:/***按协议来读数据,包括XX说:*@return:读包结果*@throwsIOException*/publicstaticStringreadPackage()throwsIOException{//开始读数据if(dins!
Exchange();
printf("\n路由表交换:
OutputRoutData();
printf("输入起始路由节点(%d-%d):
",0,ROUTNUM-1);
scanf("%d",&start);
printf("输入终点路由节点(%d-%d):
scanf("%d",&end);
if(start==end||start<0||start>6||end<0||end>6)
printf("\n输入错误,请按任意键退出\n");
intcur=start;
inttotal=0;
if(data[start][end].dis<0)
printf("没有路由路径发现!
}/*endofif*/
printf("%c->",cur+65);
while(data[cur][end].from>=0)
total+=data[cur][data[cur][end].from].dis;
printf("%c->",data[cur][end].from+65);
cur=data[cur][end].from;
}/*endofwhile*/
total+=data[cur][end].dis;
printf("%c\n总的路由距离=%d",end+65,total);
}/*endofelse*/
voidInitData(FILE*pfile)
charnum[10];
inti=0;
charc;
intm,n;
fseek(pfile,0,0);
for(m=0;!
feof(pfile)&&m<7;m++)
for(n=0;!
feof(pfile)&&n<7;n++)
while(!
feof(pfile))
c=fgetc(pfile);
if(c==',')/*读完一个数字*/
num[i]='\0';
data[m][n].dis=atoi(num);
data[m][n].from=-1;
i=0;
break;
elseif((c>='0'&&c<='9')||c=='-')/*如果读到数字或符号*/
num[i++]=c;
}/*endofelseif*/
}/*endoffor(n=0*/
}/*endoffor(m=0*/
voidOutputRoutData()
inti,j;
printf("");
for(i=0;i{printf("%c",i+65);}printf("\n");for(i=0;i{printf("%c",i+65);for(j=0;j{if(data[i][j].dis<0)/*如果无路径*/printf("-");elseif(data[i][j].dis>=10)printf("%d",data[i][j].dis);elseprintf("%d",data[i][j].dis);if(data[i][j].from<0)/*如果未经过其它节点*/printf("-");elseprintf("%c",data[i][j].from+65);}/*endoffor(j=0*/printf("\n");}/*endoffor(i=0*/}voidCommunication(intrecv,intsend){inti;for(i=0;i{if(data[send][i].dis>0)/*如果send节点到i号节点有路线*/{if(data[recv][i].dis<0)/*如果recv到i号节点无路径*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}elseif(data[recv][i].dis>data[send][i].dis+data[recv][send].dis)/*如果现有路径比新路径远*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}}/*endofif*/}/*endoffor*/}voidExchange(){inti,j;for(i=0;i{for(j=0;j{if(data[i][j].dis>0)/*如果两个节点之间有路径*/{Communication(j,i);/*将i号节点的路由表发送给j号节点*/}/*endofif*/}/*endoffor(j=0*/}/*endoffor(i=0*/}1.4.2设计思路程序先定义了一个路由表——RoutNodedata[ROUTNUM][ROUTNUM],路由表的初始信息存储在文件中,程序运行是先调用函数InitData(FILE*pfile)从文件中读取路由表的初始信息,然后输出初始路由表的信息,Communication(intrecv,intsend)函数主要是向邻近节点发送自己的路由表信息,Exchange()函数则根据新路由表信息更新自己的路由表。当所有的路由表节点都更新一遍后,整个路由表更新完毕。1.5实验结果分析1.5.1结果截图1.5.2结果分析路由表初始信息从文件读取,根据距离向量路由算法系统自动完成路由表的更新操作,最后任意输入两个路由表接点,则可得出两接点之间的最短路径。1.6实验心得体会实验是对我们应用知识的考察,通过它我们能更加了解自己的能力。这次的实验是网络课实验中最简单的一次,但我做得一点都不好,还没有写软件的概念和思想,程序也写得不好,还没有再实验课上完成的,是后来到寝室才完成的,没有通过老师的检查,幸亏我们的老师心地善良,说不用检查也可以通过。这个程序只能实现主要的功能,没有界面,也没有什么操作,因能力有限,只能做到这个样子,还望老师见谅。有空的话我一定好好学习一种编程软件。实验二网络聊天窗口2.1实验目的1,进一步加深对网络底层数据传输过程的理解2,通过自己动手编写具体的代码,实现实验的要求,提高学生的编程能力3,熟悉socket编程接口,初步掌握用socket编程接口开发面向连接的网络应用程序的方法。4,熟悉socket编程接口,初步掌握用socket编程接口开发无连接的网络应用程序的方法。2.2实验原理为实现网络聊天的功能,采用WindowsSocket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。由于服务器端要保存用户信息,我们暂时利用文件保存来实现这一功能,这是为了保存较好的可移植性,在没装相应数据库的机子上也能顺利地运行。在客户端保存用户号码这一功能的实现中,采用了文件系统设计。在不同的客户间可以实现文件的传输,其原理与信息传送差不多,只不过传输的内容是文件字节流。 服务器及客户端的功能可划分为以下模块:客户端:1)登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。(由于本项目是作者09年时出于兴趣自己开始做的,所以界面中显示的是QQ2009)用用户名字登录。密码都默认为123其中,点击界面上的“注册新账号”会出现下图:在里面填写相应的名字和密码即可注册,当然服务器也要开启相应的端口,如下:2)界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。本界面中左边和右边都是截图所得,这些按钮没有实际功能,只为了模仿QQ。3)聊天功能:与好友聊天。本界面做的时候有点bug,就是聊天窗口中只有一个有个人形象展示,如上,在左边打开的窗口中没有,右边有。这一个bug有空会改过来的。4)发送文件:能发送任一文件,当然文件不能过大,否则可能会出问题。收到的图片可以正常打开5)信息提示:闪动托盘图标提示到来信息,并播放不同音乐来提示。6)其他:用户登陆成功,将保存其号码,以便下次登陆时,不必再输入而可以直接选择,显示登陆时间。服务器端:写上一个合适的端口后点击开启端口,就可以开启一个端口用来专门接收用户的连接。当有用户上线进,就会把相应的用户列在列表中。向各个客户端发布系统消息。接受来自客户端的各种信息并分别处理。1)登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就将在线用户发给该用户,并将该用户的状态发给各在线用户。同时在服务器端显示出来。2)聊天信息:转发给消息指定的用户。3)申请信息:自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。4)用户下线:将此用户下线消息发给各客户端,并改写用户在服务器端的状态。 2.3实验具体实现1、服务器端:服务器端启动时,先初始化服务端界面,之后开启一个端口用来监听客户端的连接:ChatServer.java文件里面:publicvoidsetUpServer(){try{System.out.println(port);//创建服务端套接字server=new.ServerSocket(port);MakeLog.writeLog("成功创建了一个套接字","ChatServer");//进入一个循环来等待客户端while(true){if(server!=null){.Socketclient=server.accept();//开一个线程ServerThreadnewThread=newServerThread(client);MakeLog.writeLog("已经创建一个线程连接.客户端地址:"+client.getRemoteSocketAddress(),"ChatServer");listSock.add(client);//启动线程newThread.start();}}}catch(Exceptione){e.printStackTrace();MakeLog.writeError(e.getMessage(),"ChatServer");}}然后,当有一个客户端连接上来的时候,就开启一个线程分配给该用户,用来管理该用户的连接及一些相关的操作。(其它知识点与本实验无关,这里就不再写了,下面看客户端)2、客户端:客户端一启动时,先构造出登陆界面,当点击登陆按钮时,先做一下简单的判断,看是否账号或密码为空,当它们都合法的时候就进入下一步:/***对登陆按钮作出回应*/publicvoidreact(){if(null!=tf_name.getText()||null!=tf_psw.getText()){name=tf_name.getText().trim();psw=tf_psw.getText().trim();System.out.println("name:"+name+"psw:"+psw);//创建一个连接,连接服务器connServer(serverIp,port);ClientMng.manage(client);//登陆if(ClientMng.logon(name,psw)){ClientThreadthreadCl=newClientThread();threadCl.start();}else{javax.swing.JOptionPane.showMessageDialog(jf,"登陆失败!!用户名已登陆或密码或用户名错误!");}}else{javax.swing.JOptionPane.showMessageDialog(null,"对不起,用户名和密码不能为空!!");kk=0;}jf.dispose();//最后把登陆界面关掉。}分析代码。先用客户端内置的预设的服务器地址和端口进行socket连接信尝试,连接成功时,客户端马上给服务器发送相关的用户名和密码,服务器验证通过的时候会向客户端返回一条确认信息,客户端如果接到该确认信息说明已经登陆成功了,他们就有了一个永久性的连接,直到其中的一方关闭连接为止。其实在这过程中,还有一些环节:/***登陆用的函数*@paramname:登陆用户名*@parampsw:登陆密码*@return:是否登陆成功,true登陆成功,false登陆失败*/publicstaticbooleanlogon(Stringname,Stringpsw){myName=name;StringnamePsw;if(clientSock!=null){namePsw=name+"#"+psw;sendMsg(namePsw,"system");//发送用户名和密码try{msg=readPackage();if(msg.equals("系统说:对不起,您的用户名可能为空或未注册或已登陆!!")){//javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),//"对不起,您的用户名可能为空或未注册或已登陆!!");returnfalse;}if(msg.equals("系统说:登陆失败!!密码错误!")){javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),"登陆失败!!密码错误!");returnfalse;}sendMsg("OK!","system");msg=readPackage();sendMsg("OK!","system");//接收服务器发过来的在线用户列表names=readPackage();//处理服务器刚发过来的在线用户列表if(names!=null&&!names.equals("")){String[]s=names.split("说:");String[]allName=s[1].split("#");for(inti=0;iif(!allName[i].equals("")&&allName[i]!=null&&!exists(allName[i])){listUser.add(allName[i]);}}}//发送一条消息告诉服务器,是否需要它发送分组信息过来if(needToSendTeamInfo()){sendMsg("发过来","system");//接收服务器发过来的分组信息并保存//msg=readPackage();SaveFileAfterRecievingTeamInfo();}else{sendMsg("不用发","system");initial();}}catch(Exceptionef){ef.printStackTrace();}returntrue;}returntrue;}当客户端发送了用户名和密码之后,如果收到的信息是:“对不起,您的用户名可能为空或未注册或已登陆!!”则说明重复登陆,登陆失败。如果收到的信息是:“登陆失败!!密码错误!”则说明是密码错误,当然也有可能是不存在这个用户。收到的信息如果是其它的情况,则登陆成功,这时,双方还会再各发条“OK”信息来确认双方的连接并协调步伐。之后,客户端会判断本地是否已经有相关的列表信息,如果有,则会直接读取本地好友列表信息,如果没有的话,会请求服务器发送相关的好友列表。收到好友列表后,再解析,并构建成一棵树,显示在界面的列表项中。客户端有一个工具类,里面有一个读取消息并分解消息的方法:/***按协议来读数据,包括XX说:*@return:读包结果*@throwsIOException*/publicstaticStringreadPackage()throwsIOException{//开始读数据if(dins!
printf("%c",i+65);
for(i=0;i{printf("%c",i+65);for(j=0;j{if(data[i][j].dis<0)/*如果无路径*/printf("-");elseif(data[i][j].dis>=10)printf("%d",data[i][j].dis);elseprintf("%d",data[i][j].dis);if(data[i][j].from<0)/*如果未经过其它节点*/printf("-");elseprintf("%c",data[i][j].from+65);}/*endoffor(j=0*/printf("\n");}/*endoffor(i=0*/}voidCommunication(intrecv,intsend){inti;for(i=0;i{if(data[send][i].dis>0)/*如果send节点到i号节点有路线*/{if(data[recv][i].dis<0)/*如果recv到i号节点无路径*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}elseif(data[recv][i].dis>data[send][i].dis+data[recv][send].dis)/*如果现有路径比新路径远*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}}/*endofif*/}/*endoffor*/}voidExchange(){inti,j;for(i=0;i{for(j=0;j{if(data[i][j].dis>0)/*如果两个节点之间有路径*/{Communication(j,i);/*将i号节点的路由表发送给j号节点*/}/*endofif*/}/*endoffor(j=0*/}/*endoffor(i=0*/}1.4.2设计思路程序先定义了一个路由表——RoutNodedata[ROUTNUM][ROUTNUM],路由表的初始信息存储在文件中,程序运行是先调用函数InitData(FILE*pfile)从文件中读取路由表的初始信息,然后输出初始路由表的信息,Communication(intrecv,intsend)函数主要是向邻近节点发送自己的路由表信息,Exchange()函数则根据新路由表信息更新自己的路由表。当所有的路由表节点都更新一遍后,整个路由表更新完毕。1.5实验结果分析1.5.1结果截图1.5.2结果分析路由表初始信息从文件读取,根据距离向量路由算法系统自动完成路由表的更新操作,最后任意输入两个路由表接点,则可得出两接点之间的最短路径。1.6实验心得体会实验是对我们应用知识的考察,通过它我们能更加了解自己的能力。这次的实验是网络课实验中最简单的一次,但我做得一点都不好,还没有写软件的概念和思想,程序也写得不好,还没有再实验课上完成的,是后来到寝室才完成的,没有通过老师的检查,幸亏我们的老师心地善良,说不用检查也可以通过。这个程序只能实现主要的功能,没有界面,也没有什么操作,因能力有限,只能做到这个样子,还望老师见谅。有空的话我一定好好学习一种编程软件。实验二网络聊天窗口2.1实验目的1,进一步加深对网络底层数据传输过程的理解2,通过自己动手编写具体的代码,实现实验的要求,提高学生的编程能力3,熟悉socket编程接口,初步掌握用socket编程接口开发面向连接的网络应用程序的方法。4,熟悉socket编程接口,初步掌握用socket编程接口开发无连接的网络应用程序的方法。2.2实验原理为实现网络聊天的功能,采用WindowsSocket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。由于服务器端要保存用户信息,我们暂时利用文件保存来实现这一功能,这是为了保存较好的可移植性,在没装相应数据库的机子上也能顺利地运行。在客户端保存用户号码这一功能的实现中,采用了文件系统设计。在不同的客户间可以实现文件的传输,其原理与信息传送差不多,只不过传输的内容是文件字节流。 服务器及客户端的功能可划分为以下模块:客户端:1)登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。(由于本项目是作者09年时出于兴趣自己开始做的,所以界面中显示的是QQ2009)用用户名字登录。密码都默认为123其中,点击界面上的“注册新账号”会出现下图:在里面填写相应的名字和密码即可注册,当然服务器也要开启相应的端口,如下:2)界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。本界面中左边和右边都是截图所得,这些按钮没有实际功能,只为了模仿QQ。3)聊天功能:与好友聊天。本界面做的时候有点bug,就是聊天窗口中只有一个有个人形象展示,如上,在左边打开的窗口中没有,右边有。这一个bug有空会改过来的。4)发送文件:能发送任一文件,当然文件不能过大,否则可能会出问题。收到的图片可以正常打开5)信息提示:闪动托盘图标提示到来信息,并播放不同音乐来提示。6)其他:用户登陆成功,将保存其号码,以便下次登陆时,不必再输入而可以直接选择,显示登陆时间。服务器端:写上一个合适的端口后点击开启端口,就可以开启一个端口用来专门接收用户的连接。当有用户上线进,就会把相应的用户列在列表中。向各个客户端发布系统消息。接受来自客户端的各种信息并分别处理。1)登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就将在线用户发给该用户,并将该用户的状态发给各在线用户。同时在服务器端显示出来。2)聊天信息:转发给消息指定的用户。3)申请信息:自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。4)用户下线:将此用户下线消息发给各客户端,并改写用户在服务器端的状态。 2.3实验具体实现1、服务器端:服务器端启动时,先初始化服务端界面,之后开启一个端口用来监听客户端的连接:ChatServer.java文件里面:publicvoidsetUpServer(){try{System.out.println(port);//创建服务端套接字server=new.ServerSocket(port);MakeLog.writeLog("成功创建了一个套接字","ChatServer");//进入一个循环来等待客户端while(true){if(server!=null){.Socketclient=server.accept();//开一个线程ServerThreadnewThread=newServerThread(client);MakeLog.writeLog("已经创建一个线程连接.客户端地址:"+client.getRemoteSocketAddress(),"ChatServer");listSock.add(client);//启动线程newThread.start();}}}catch(Exceptione){e.printStackTrace();MakeLog.writeError(e.getMessage(),"ChatServer");}}然后,当有一个客户端连接上来的时候,就开启一个线程分配给该用户,用来管理该用户的连接及一些相关的操作。(其它知识点与本实验无关,这里就不再写了,下面看客户端)2、客户端:客户端一启动时,先构造出登陆界面,当点击登陆按钮时,先做一下简单的判断,看是否账号或密码为空,当它们都合法的时候就进入下一步:/***对登陆按钮作出回应*/publicvoidreact(){if(null!=tf_name.getText()||null!=tf_psw.getText()){name=tf_name.getText().trim();psw=tf_psw.getText().trim();System.out.println("name:"+name+"psw:"+psw);//创建一个连接,连接服务器connServer(serverIp,port);ClientMng.manage(client);//登陆if(ClientMng.logon(name,psw)){ClientThreadthreadCl=newClientThread();threadCl.start();}else{javax.swing.JOptionPane.showMessageDialog(jf,"登陆失败!!用户名已登陆或密码或用户名错误!");}}else{javax.swing.JOptionPane.showMessageDialog(null,"对不起,用户名和密码不能为空!!");kk=0;}jf.dispose();//最后把登陆界面关掉。}分析代码。先用客户端内置的预设的服务器地址和端口进行socket连接信尝试,连接成功时,客户端马上给服务器发送相关的用户名和密码,服务器验证通过的时候会向客户端返回一条确认信息,客户端如果接到该确认信息说明已经登陆成功了,他们就有了一个永久性的连接,直到其中的一方关闭连接为止。其实在这过程中,还有一些环节:/***登陆用的函数*@paramname:登陆用户名*@parampsw:登陆密码*@return:是否登陆成功,true登陆成功,false登陆失败*/publicstaticbooleanlogon(Stringname,Stringpsw){myName=name;StringnamePsw;if(clientSock!=null){namePsw=name+"#"+psw;sendMsg(namePsw,"system");//发送用户名和密码try{msg=readPackage();if(msg.equals("系统说:对不起,您的用户名可能为空或未注册或已登陆!!")){//javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),//"对不起,您的用户名可能为空或未注册或已登陆!!");returnfalse;}if(msg.equals("系统说:登陆失败!!密码错误!")){javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),"登陆失败!!密码错误!");returnfalse;}sendMsg("OK!","system");msg=readPackage();sendMsg("OK!","system");//接收服务器发过来的在线用户列表names=readPackage();//处理服务器刚发过来的在线用户列表if(names!=null&&!names.equals("")){String[]s=names.split("说:");String[]allName=s[1].split("#");for(inti=0;iif(!allName[i].equals("")&&allName[i]!=null&&!exists(allName[i])){listUser.add(allName[i]);}}}//发送一条消息告诉服务器,是否需要它发送分组信息过来if(needToSendTeamInfo()){sendMsg("发过来","system");//接收服务器发过来的分组信息并保存//msg=readPackage();SaveFileAfterRecievingTeamInfo();}else{sendMsg("不用发","system");initial();}}catch(Exceptionef){ef.printStackTrace();}returntrue;}returntrue;}当客户端发送了用户名和密码之后,如果收到的信息是:“对不起,您的用户名可能为空或未注册或已登陆!!”则说明重复登陆,登陆失败。如果收到的信息是:“登陆失败!!密码错误!”则说明是密码错误,当然也有可能是不存在这个用户。收到的信息如果是其它的情况,则登陆成功,这时,双方还会再各发条“OK”信息来确认双方的连接并协调步伐。之后,客户端会判断本地是否已经有相关的列表信息,如果有,则会直接读取本地好友列表信息,如果没有的话,会请求服务器发送相关的好友列表。收到好友列表后,再解析,并构建成一棵树,显示在界面的列表项中。客户端有一个工具类,里面有一个读取消息并分解消息的方法:/***按协议来读数据,包括XX说:*@return:读包结果*@throwsIOException*/publicstaticStringreadPackage()throwsIOException{//开始读数据if(dins!
for(j=0;j{if(data[i][j].dis<0)/*如果无路径*/printf("-");elseif(data[i][j].dis>=10)printf("%d",data[i][j].dis);elseprintf("%d",data[i][j].dis);if(data[i][j].from<0)/*如果未经过其它节点*/printf("-");elseprintf("%c",data[i][j].from+65);}/*endoffor(j=0*/printf("\n");}/*endoffor(i=0*/}voidCommunication(intrecv,intsend){inti;for(i=0;i{if(data[send][i].dis>0)/*如果send节点到i号节点有路线*/{if(data[recv][i].dis<0)/*如果recv到i号节点无路径*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}elseif(data[recv][i].dis>data[send][i].dis+data[recv][send].dis)/*如果现有路径比新路径远*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}}/*endofif*/}/*endoffor*/}voidExchange(){inti,j;for(i=0;i{for(j=0;j{if(data[i][j].dis>0)/*如果两个节点之间有路径*/{Communication(j,i);/*将i号节点的路由表发送给j号节点*/}/*endofif*/}/*endoffor(j=0*/}/*endoffor(i=0*/}1.4.2设计思路程序先定义了一个路由表——RoutNodedata[ROUTNUM][ROUTNUM],路由表的初始信息存储在文件中,程序运行是先调用函数InitData(FILE*pfile)从文件中读取路由表的初始信息,然后输出初始路由表的信息,Communication(intrecv,intsend)函数主要是向邻近节点发送自己的路由表信息,Exchange()函数则根据新路由表信息更新自己的路由表。当所有的路由表节点都更新一遍后,整个路由表更新完毕。1.5实验结果分析1.5.1结果截图1.5.2结果分析路由表初始信息从文件读取,根据距离向量路由算法系统自动完成路由表的更新操作,最后任意输入两个路由表接点,则可得出两接点之间的最短路径。1.6实验心得体会实验是对我们应用知识的考察,通过它我们能更加了解自己的能力。这次的实验是网络课实验中最简单的一次,但我做得一点都不好,还没有写软件的概念和思想,程序也写得不好,还没有再实验课上完成的,是后来到寝室才完成的,没有通过老师的检查,幸亏我们的老师心地善良,说不用检查也可以通过。这个程序只能实现主要的功能,没有界面,也没有什么操作,因能力有限,只能做到这个样子,还望老师见谅。有空的话我一定好好学习一种编程软件。实验二网络聊天窗口2.1实验目的1,进一步加深对网络底层数据传输过程的理解2,通过自己动手编写具体的代码,实现实验的要求,提高学生的编程能力3,熟悉socket编程接口,初步掌握用socket编程接口开发面向连接的网络应用程序的方法。4,熟悉socket编程接口,初步掌握用socket编程接口开发无连接的网络应用程序的方法。2.2实验原理为实现网络聊天的功能,采用WindowsSocket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。由于服务器端要保存用户信息,我们暂时利用文件保存来实现这一功能,这是为了保存较好的可移植性,在没装相应数据库的机子上也能顺利地运行。在客户端保存用户号码这一功能的实现中,采用了文件系统设计。在不同的客户间可以实现文件的传输,其原理与信息传送差不多,只不过传输的内容是文件字节流。 服务器及客户端的功能可划分为以下模块:客户端:1)登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。(由于本项目是作者09年时出于兴趣自己开始做的,所以界面中显示的是QQ2009)用用户名字登录。密码都默认为123其中,点击界面上的“注册新账号”会出现下图:在里面填写相应的名字和密码即可注册,当然服务器也要开启相应的端口,如下:2)界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。本界面中左边和右边都是截图所得,这些按钮没有实际功能,只为了模仿QQ。3)聊天功能:与好友聊天。本界面做的时候有点bug,就是聊天窗口中只有一个有个人形象展示,如上,在左边打开的窗口中没有,右边有。这一个bug有空会改过来的。4)发送文件:能发送任一文件,当然文件不能过大,否则可能会出问题。收到的图片可以正常打开5)信息提示:闪动托盘图标提示到来信息,并播放不同音乐来提示。6)其他:用户登陆成功,将保存其号码,以便下次登陆时,不必再输入而可以直接选择,显示登陆时间。服务器端:写上一个合适的端口后点击开启端口,就可以开启一个端口用来专门接收用户的连接。当有用户上线进,就会把相应的用户列在列表中。向各个客户端发布系统消息。接受来自客户端的各种信息并分别处理。1)登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就将在线用户发给该用户,并将该用户的状态发给各在线用户。同时在服务器端显示出来。2)聊天信息:转发给消息指定的用户。3)申请信息:自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。4)用户下线:将此用户下线消息发给各客户端,并改写用户在服务器端的状态。 2.3实验具体实现1、服务器端:服务器端启动时,先初始化服务端界面,之后开启一个端口用来监听客户端的连接:ChatServer.java文件里面:publicvoidsetUpServer(){try{System.out.println(port);//创建服务端套接字server=new.ServerSocket(port);MakeLog.writeLog("成功创建了一个套接字","ChatServer");//进入一个循环来等待客户端while(true){if(server!=null){.Socketclient=server.accept();//开一个线程ServerThreadnewThread=newServerThread(client);MakeLog.writeLog("已经创建一个线程连接.客户端地址:"+client.getRemoteSocketAddress(),"ChatServer");listSock.add(client);//启动线程newThread.start();}}}catch(Exceptione){e.printStackTrace();MakeLog.writeError(e.getMessage(),"ChatServer");}}然后,当有一个客户端连接上来的时候,就开启一个线程分配给该用户,用来管理该用户的连接及一些相关的操作。(其它知识点与本实验无关,这里就不再写了,下面看客户端)2、客户端:客户端一启动时,先构造出登陆界面,当点击登陆按钮时,先做一下简单的判断,看是否账号或密码为空,当它们都合法的时候就进入下一步:/***对登陆按钮作出回应*/publicvoidreact(){if(null!=tf_name.getText()||null!=tf_psw.getText()){name=tf_name.getText().trim();psw=tf_psw.getText().trim();System.out.println("name:"+name+"psw:"+psw);//创建一个连接,连接服务器connServer(serverIp,port);ClientMng.manage(client);//登陆if(ClientMng.logon(name,psw)){ClientThreadthreadCl=newClientThread();threadCl.start();}else{javax.swing.JOptionPane.showMessageDialog(jf,"登陆失败!!用户名已登陆或密码或用户名错误!");}}else{javax.swing.JOptionPane.showMessageDialog(null,"对不起,用户名和密码不能为空!!");kk=0;}jf.dispose();//最后把登陆界面关掉。}分析代码。先用客户端内置的预设的服务器地址和端口进行socket连接信尝试,连接成功时,客户端马上给服务器发送相关的用户名和密码,服务器验证通过的时候会向客户端返回一条确认信息,客户端如果接到该确认信息说明已经登陆成功了,他们就有了一个永久性的连接,直到其中的一方关闭连接为止。其实在这过程中,还有一些环节:/***登陆用的函数*@paramname:登陆用户名*@parampsw:登陆密码*@return:是否登陆成功,true登陆成功,false登陆失败*/publicstaticbooleanlogon(Stringname,Stringpsw){myName=name;StringnamePsw;if(clientSock!=null){namePsw=name+"#"+psw;sendMsg(namePsw,"system");//发送用户名和密码try{msg=readPackage();if(msg.equals("系统说:对不起,您的用户名可能为空或未注册或已登陆!!")){//javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),//"对不起,您的用户名可能为空或未注册或已登陆!!");returnfalse;}if(msg.equals("系统说:登陆失败!!密码错误!")){javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),"登陆失败!!密码错误!");returnfalse;}sendMsg("OK!","system");msg=readPackage();sendMsg("OK!","system");//接收服务器发过来的在线用户列表names=readPackage();//处理服务器刚发过来的在线用户列表if(names!=null&&!names.equals("")){String[]s=names.split("说:");String[]allName=s[1].split("#");for(inti=0;iif(!allName[i].equals("")&&allName[i]!=null&&!exists(allName[i])){listUser.add(allName[i]);}}}//发送一条消息告诉服务器,是否需要它发送分组信息过来if(needToSendTeamInfo()){sendMsg("发过来","system");//接收服务器发过来的分组信息并保存//msg=readPackage();SaveFileAfterRecievingTeamInfo();}else{sendMsg("不用发","system");initial();}}catch(Exceptionef){ef.printStackTrace();}returntrue;}returntrue;}当客户端发送了用户名和密码之后,如果收到的信息是:“对不起,您的用户名可能为空或未注册或已登陆!!”则说明重复登陆,登陆失败。如果收到的信息是:“登陆失败!!密码错误!”则说明是密码错误,当然也有可能是不存在这个用户。收到的信息如果是其它的情况,则登陆成功,这时,双方还会再各发条“OK”信息来确认双方的连接并协调步伐。之后,客户端会判断本地是否已经有相关的列表信息,如果有,则会直接读取本地好友列表信息,如果没有的话,会请求服务器发送相关的好友列表。收到好友列表后,再解析,并构建成一棵树,显示在界面的列表项中。客户端有一个工具类,里面有一个读取消息并分解消息的方法:/***按协议来读数据,包括XX说:*@return:读包结果*@throwsIOException*/publicstaticStringreadPackage()throwsIOException{//开始读数据if(dins!
if(data[i][j].dis<0)/*如果无路径*/
printf("-");
if(data[i][j].dis>=10)
printf("%d",data[i][j].dis);
if(data[i][j].from<0)/*如果未经过其它节点*/
printf("%c",data[i][j].from+65);
}/*endoffor(j=0*/
}/*endoffor(i=0*/
voidCommunication(intrecv,intsend)
inti;
for(i=0;i{if(data[send][i].dis>0)/*如果send节点到i号节点有路线*/{if(data[recv][i].dis<0)/*如果recv到i号节点无路径*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}elseif(data[recv][i].dis>data[send][i].dis+data[recv][send].dis)/*如果现有路径比新路径远*/{data[recv][i].dis=data[send][i].dis+data[recv][send].dis;data[recv][i].from=send;}}/*endofif*/}/*endoffor*/}voidExchange(){inti,j;for(i=0;i{for(j=0;j{if(data[i][j].dis>0)/*如果两个节点之间有路径*/{Communication(j,i);/*将i号节点的路由表发送给j号节点*/}/*endofif*/}/*endoffor(j=0*/}/*endoffor(i=0*/}1.4.2设计思路程序先定义了一个路由表——RoutNodedata[ROUTNUM][ROUTNUM],路由表的初始信息存储在文件中,程序运行是先调用函数InitData(FILE*pfile)从文件中读取路由表的初始信息,然后输出初始路由表的信息,Communication(intrecv,intsend)函数主要是向邻近节点发送自己的路由表信息,Exchange()函数则根据新路由表信息更新自己的路由表。当所有的路由表节点都更新一遍后,整个路由表更新完毕。1.5实验结果分析1.5.1结果截图1.5.2结果分析路由表初始信息从文件读取,根据距离向量路由算法系统自动完成路由表的更新操作,最后任意输入两个路由表接点,则可得出两接点之间的最短路径。1.6实验心得体会实验是对我们应用知识的考察,通过它我们能更加了解自己的能力。这次的实验是网络课实验中最简单的一次,但我做得一点都不好,还没有写软件的概念和思想,程序也写得不好,还没有再实验课上完成的,是后来到寝室才完成的,没有通过老师的检查,幸亏我们的老师心地善良,说不用检查也可以通过。这个程序只能实现主要的功能,没有界面,也没有什么操作,因能力有限,只能做到这个样子,还望老师见谅。有空的话我一定好好学习一种编程软件。实验二网络聊天窗口2.1实验目的1,进一步加深对网络底层数据传输过程的理解2,通过自己动手编写具体的代码,实现实验的要求,提高学生的编程能力3,熟悉socket编程接口,初步掌握用socket编程接口开发面向连接的网络应用程序的方法。4,熟悉socket编程接口,初步掌握用socket编程接口开发无连接的网络应用程序的方法。2.2实验原理为实现网络聊天的功能,采用WindowsSocket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。由于服务器端要保存用户信息,我们暂时利用文件保存来实现这一功能,这是为了保存较好的可移植性,在没装相应数据库的机子上也能顺利地运行。在客户端保存用户号码这一功能的实现中,采用了文件系统设计。在不同的客户间可以实现文件的传输,其原理与信息传送差不多,只不过传输的内容是文件字节流。 服务器及客户端的功能可划分为以下模块:客户端:1)登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。(由于本项目是作者09年时出于兴趣自己开始做的,所以界面中显示的是QQ2009)用用户名字登录。密码都默认为123其中,点击界面上的“注册新账号”会出现下图:在里面填写相应的名字和密码即可注册,当然服务器也要开启相应的端口,如下:2)界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。本界面中左边和右边都是截图所得,这些按钮没有实际功能,只为了模仿QQ。3)聊天功能:与好友聊天。本界面做的时候有点bug,就是聊天窗口中只有一个有个人形象展示,如上,在左边打开的窗口中没有,右边有。这一个bug有空会改过来的。4)发送文件:能发送任一文件,当然文件不能过大,否则可能会出问题。收到的图片可以正常打开5)信息提示:闪动托盘图标提示到来信息,并播放不同音乐来提示。6)其他:用户登陆成功,将保存其号码,以便下次登陆时,不必再输入而可以直接选择,显示登陆时间。服务器端:写上一个合适的端口后点击开启端口,就可以开启一个端口用来专门接收用户的连接。当有用户上线进,就会把相应的用户列在列表中。向各个客户端发布系统消息。接受来自客户端的各种信息并分别处理。1)登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就将在线用户发给该用户,并将该用户的状态发给各在线用户。同时在服务器端显示出来。2)聊天信息:转发给消息指定的用户。3)申请信息:自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。4)用户下线:将此用户下线消息发给各客户端,并改写用户在服务器端的状态。 2.3实验具体实现1、服务器端:服务器端启动时,先初始化服务端界面,之后开启一个端口用来监听客户端的连接:ChatServer.java文件里面:publicvoidsetUpServer(){try{System.out.println(port);//创建服务端套接字server=new.ServerSocket(port);MakeLog.writeLog("成功创建了一个套接字","ChatServer");//进入一个循环来等待客户端while(true){if(server!=null){.Socketclient=server.accept();//开一个线程ServerThreadnewThread=newServerThread(client);MakeLog.writeLog("已经创建一个线程连接.客户端地址:"+client.getRemoteSocketAddress(),"ChatServer");listSock.add(client);//启动线程newThread.start();}}}catch(Exceptione){e.printStackTrace();MakeLog.writeError(e.getMessage(),"ChatServer");}}然后,当有一个客户端连接上来的时候,就开启一个线程分配给该用户,用来管理该用户的连接及一些相关的操作。(其它知识点与本实验无关,这里就不再写了,下面看客户端)2、客户端:客户端一启动时,先构造出登陆界面,当点击登陆按钮时,先做一下简单的判断,看是否账号或密码为空,当它们都合法的时候就进入下一步:/***对登陆按钮作出回应*/publicvoidreact(){if(null!=tf_name.getText()||null!=tf_psw.getText()){name=tf_name.getText().trim();psw=tf_psw.getText().trim();System.out.println("name:"+name+"psw:"+psw);//创建一个连接,连接服务器connServer(serverIp,port);ClientMng.manage(client);//登陆if(ClientMng.logon(name,psw)){ClientThreadthreadCl=newClientThread();threadCl.start();}else{javax.swing.JOptionPane.showMessageDialog(jf,"登陆失败!!用户名已登陆或密码或用户名错误!");}}else{javax.swing.JOptionPane.showMessageDialog(null,"对不起,用户名和密码不能为空!!");kk=0;}jf.dispose();//最后把登陆界面关掉。}分析代码。先用客户端内置的预设的服务器地址和端口进行socket连接信尝试,连接成功时,客户端马上给服务器发送相关的用户名和密码,服务器验证通过的时候会向客户端返回一条确认信息,客户端如果接到该确认信息说明已经登陆成功了,他们就有了一个永久性的连接,直到其中的一方关闭连接为止。其实在这过程中,还有一些环节:/***登陆用的函数*@paramname:登陆用户名*@parampsw:登陆密码*@return:是否登陆成功,true登陆成功,false登陆失败*/publicstaticbooleanlogon(Stringname,Stringpsw){myName=name;StringnamePsw;if(clientSock!=null){namePsw=name+"#"+psw;sendMsg(namePsw,"system");//发送用户名和密码try{msg=readPackage();if(msg.equals("系统说:对不起,您的用户名可能为空或未注册或已登陆!!")){//javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),//"对不起,您的用户名可能为空或未注册或已登陆!!");returnfalse;}if(msg.equals("系统说:登陆失败!!密码错误!")){javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),"登陆失败!!密码错误!");returnfalse;}sendMsg("OK!","system");msg=readPackage();sendMsg("OK!","system");//接收服务器发过来的在线用户列表names=readPackage();//处理服务器刚发过来的在线用户列表if(names!=null&&!names.equals("")){String[]s=names.split("说:");String[]allName=s[1].split("#");for(inti=0;iif(!allName[i].equals("")&&allName[i]!=null&&!exists(allName[i])){listUser.add(allName[i]);}}}//发送一条消息告诉服务器,是否需要它发送分组信息过来if(needToSendTeamInfo()){sendMsg("发过来","system");//接收服务器发过来的分组信息并保存//msg=readPackage();SaveFileAfterRecievingTeamInfo();}else{sendMsg("不用发","system");initial();}}catch(Exceptionef){ef.printStackTrace();}returntrue;}returntrue;}当客户端发送了用户名和密码之后,如果收到的信息是:“对不起,您的用户名可能为空或未注册或已登陆!!”则说明重复登陆,登陆失败。如果收到的信息是:“登陆失败!!密码错误!”则说明是密码错误,当然也有可能是不存在这个用户。收到的信息如果是其它的情况,则登陆成功,这时,双方还会再各发条“OK”信息来确认双方的连接并协调步伐。之后,客户端会判断本地是否已经有相关的列表信息,如果有,则会直接读取本地好友列表信息,如果没有的话,会请求服务器发送相关的好友列表。收到好友列表后,再解析,并构建成一棵树,显示在界面的列表项中。客户端有一个工具类,里面有一个读取消息并分解消息的方法:/***按协议来读数据,包括XX说:*@return:读包结果*@throwsIOException*/publicstaticStringreadPackage()throwsIOException{//开始读数据if(dins!
if(data[send][i].dis>0)/*如果send节点到i号节点有路线*/
if(data[recv][i].dis<0)/*如果recv到i号节点无路径*/
data[recv][i].dis=data[send][i].dis+data[recv][send].dis;
data[recv][i].from=send;
elseif(data[recv][i].dis>data[send][i].dis+data[recv][send].dis)
/*如果现有路径比新路径远*/
}/*endoffor*/
voidExchange()
for(i=0;i{for(j=0;j{if(data[i][j].dis>0)/*如果两个节点之间有路径*/{Communication(j,i);/*将i号节点的路由表发送给j号节点*/}/*endofif*/}/*endoffor(j=0*/}/*endoffor(i=0*/}1.4.2设计思路程序先定义了一个路由表——RoutNodedata[ROUTNUM][ROUTNUM],路由表的初始信息存储在文件中,程序运行是先调用函数InitData(FILE*pfile)从文件中读取路由表的初始信息,然后输出初始路由表的信息,Communication(intrecv,intsend)函数主要是向邻近节点发送自己的路由表信息,Exchange()函数则根据新路由表信息更新自己的路由表。当所有的路由表节点都更新一遍后,整个路由表更新完毕。1.5实验结果分析1.5.1结果截图1.5.2结果分析路由表初始信息从文件读取,根据距离向量路由算法系统自动完成路由表的更新操作,最后任意输入两个路由表接点,则可得出两接点之间的最短路径。1.6实验心得体会实验是对我们应用知识的考察,通过它我们能更加了解自己的能力。这次的实验是网络课实验中最简单的一次,但我做得一点都不好,还没有写软件的概念和思想,程序也写得不好,还没有再实验课上完成的,是后来到寝室才完成的,没有通过老师的检查,幸亏我们的老师心地善良,说不用检查也可以通过。这个程序只能实现主要的功能,没有界面,也没有什么操作,因能力有限,只能做到这个样子,还望老师见谅。有空的话我一定好好学习一种编程软件。实验二网络聊天窗口2.1实验目的1,进一步加深对网络底层数据传输过程的理解2,通过自己动手编写具体的代码,实现实验的要求,提高学生的编程能力3,熟悉socket编程接口,初步掌握用socket编程接口开发面向连接的网络应用程序的方法。4,熟悉socket编程接口,初步掌握用socket编程接口开发无连接的网络应用程序的方法。2.2实验原理为实现网络聊天的功能,采用WindowsSocket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。由于服务器端要保存用户信息,我们暂时利用文件保存来实现这一功能,这是为了保存较好的可移植性,在没装相应数据库的机子上也能顺利地运行。在客户端保存用户号码这一功能的实现中,采用了文件系统设计。在不同的客户间可以实现文件的传输,其原理与信息传送差不多,只不过传输的内容是文件字节流。 服务器及客户端的功能可划分为以下模块:客户端:1)登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。(由于本项目是作者09年时出于兴趣自己开始做的,所以界面中显示的是QQ2009)用用户名字登录。密码都默认为123其中,点击界面上的“注册新账号”会出现下图:在里面填写相应的名字和密码即可注册,当然服务器也要开启相应的端口,如下:2)界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。本界面中左边和右边都是截图所得,这些按钮没有实际功能,只为了模仿QQ。3)聊天功能:与好友聊天。本界面做的时候有点bug,就是聊天窗口中只有一个有个人形象展示,如上,在左边打开的窗口中没有,右边有。这一个bug有空会改过来的。4)发送文件:能发送任一文件,当然文件不能过大,否则可能会出问题。收到的图片可以正常打开5)信息提示:闪动托盘图标提示到来信息,并播放不同音乐来提示。6)其他:用户登陆成功,将保存其号码,以便下次登陆时,不必再输入而可以直接选择,显示登陆时间。服务器端:写上一个合适的端口后点击开启端口,就可以开启一个端口用来专门接收用户的连接。当有用户上线进,就会把相应的用户列在列表中。向各个客户端发布系统消息。接受来自客户端的各种信息并分别处理。1)登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就将在线用户发给该用户,并将该用户的状态发给各在线用户。同时在服务器端显示出来。2)聊天信息:转发给消息指定的用户。3)申请信息:自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。4)用户下线:将此用户下线消息发给各客户端,并改写用户在服务器端的状态。 2.3实验具体实现1、服务器端:服务器端启动时,先初始化服务端界面,之后开启一个端口用来监听客户端的连接:ChatServer.java文件里面:publicvoidsetUpServer(){try{System.out.println(port);//创建服务端套接字server=new.ServerSocket(port);MakeLog.writeLog("成功创建了一个套接字","ChatServer");//进入一个循环来等待客户端while(true){if(server!=null){.Socketclient=server.accept();//开一个线程ServerThreadnewThread=newServerThread(client);MakeLog.writeLog("已经创建一个线程连接.客户端地址:"+client.getRemoteSocketAddress(),"ChatServer");listSock.add(client);//启动线程newThread.start();}}}catch(Exceptione){e.printStackTrace();MakeLog.writeError(e.getMessage(),"ChatServer");}}然后,当有一个客户端连接上来的时候,就开启一个线程分配给该用户,用来管理该用户的连接及一些相关的操作。(其它知识点与本实验无关,这里就不再写了,下面看客户端)2、客户端:客户端一启动时,先构造出登陆界面,当点击登陆按钮时,先做一下简单的判断,看是否账号或密码为空,当它们都合法的时候就进入下一步:/***对登陆按钮作出回应*/publicvoidreact(){if(null!=tf_name.getText()||null!=tf_psw.getText()){name=tf_name.getText().trim();psw=tf_psw.getText().trim();System.out.println("name:"+name+"psw:"+psw);//创建一个连接,连接服务器connServer(serverIp,port);ClientMng.manage(client);//登陆if(ClientMng.logon(name,psw)){ClientThreadthreadCl=newClientThread();threadCl.start();}else{javax.swing.JOptionPane.showMessageDialog(jf,"登陆失败!!用户名已登陆或密码或用户名错误!");}}else{javax.swing.JOptionPane.showMessageDialog(null,"对不起,用户名和密码不能为空!!");kk=0;}jf.dispose();//最后把登陆界面关掉。}分析代码。先用客户端内置的预设的服务器地址和端口进行socket连接信尝试,连接成功时,客户端马上给服务器发送相关的用户名和密码,服务器验证通过的时候会向客户端返回一条确认信息,客户端如果接到该确认信息说明已经登陆成功了,他们就有了一个永久性的连接,直到其中的一方关闭连接为止。其实在这过程中,还有一些环节:/***登陆用的函数*@paramname:登陆用户名*@parampsw:登陆密码*@return:是否登陆成功,true登陆成功,false登陆失败*/publicstaticbooleanlogon(Stringname,Stringpsw){myName=name;StringnamePsw;if(clientSock!=null){namePsw=name+"#"+psw;sendMsg(namePsw,"system");//发送用户名和密码try{msg=readPackage();if(msg.equals("系统说:对不起,您的用户名可能为空或未注册或已登陆!!")){//javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),//"对不起,您的用户名可能为空或未注册或已登陆!!");returnfalse;}if(msg.equals("系统说:登陆失败!!密码错误!")){javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),"登陆失败!!密码错误!");returnfalse;}sendMsg("OK!","system");msg=readPackage();sendMsg("OK!","system");//接收服务器发过来的在线用户列表names=readPackage();//处理服务器刚发过来的在线用户列表if(names!=null&&!names.equals("")){String[]s=names.split("说:");String[]allName=s[1].split("#");for(inti=0;iif(!allName[i].equals("")&&allName[i]!=null&&!exists(allName[i])){listUser.add(allName[i]);}}}//发送一条消息告诉服务器,是否需要它发送分组信息过来if(needToSendTeamInfo()){sendMsg("发过来","system");//接收服务器发过来的分组信息并保存//msg=readPackage();SaveFileAfterRecievingTeamInfo();}else{sendMsg("不用发","system");initial();}}catch(Exceptionef){ef.printStackTrace();}returntrue;}returntrue;}当客户端发送了用户名和密码之后,如果收到的信息是:“对不起,您的用户名可能为空或未注册或已登陆!!”则说明重复登陆,登陆失败。如果收到的信息是:“登陆失败!!密码错误!”则说明是密码错误,当然也有可能是不存在这个用户。收到的信息如果是其它的情况,则登陆成功,这时,双方还会再各发条“OK”信息来确认双方的连接并协调步伐。之后,客户端会判断本地是否已经有相关的列表信息,如果有,则会直接读取本地好友列表信息,如果没有的话,会请求服务器发送相关的好友列表。收到好友列表后,再解析,并构建成一棵树,显示在界面的列表项中。客户端有一个工具类,里面有一个读取消息并分解消息的方法:/***按协议来读数据,包括XX说:*@return:读包结果*@throwsIOException*/publicstaticStringreadPackage()throwsIOException{//开始读数据if(dins!
for(j=0;j{if(data[i][j].dis>0)/*如果两个节点之间有路径*/{Communication(j,i);/*将i号节点的路由表发送给j号节点*/}/*endofif*/}/*endoffor(j=0*/}/*endoffor(i=0*/}1.4.2设计思路程序先定义了一个路由表——RoutNodedata[ROUTNUM][ROUTNUM],路由表的初始信息存储在文件中,程序运行是先调用函数InitData(FILE*pfile)从文件中读取路由表的初始信息,然后输出初始路由表的信息,Communication(intrecv,intsend)函数主要是向邻近节点发送自己的路由表信息,Exchange()函数则根据新路由表信息更新自己的路由表。当所有的路由表节点都更新一遍后,整个路由表更新完毕。1.5实验结果分析1.5.1结果截图1.5.2结果分析路由表初始信息从文件读取,根据距离向量路由算法系统自动完成路由表的更新操作,最后任意输入两个路由表接点,则可得出两接点之间的最短路径。1.6实验心得体会实验是对我们应用知识的考察,通过它我们能更加了解自己的能力。这次的实验是网络课实验中最简单的一次,但我做得一点都不好,还没有写软件的概念和思想,程序也写得不好,还没有再实验课上完成的,是后来到寝室才完成的,没有通过老师的检查,幸亏我们的老师心地善良,说不用检查也可以通过。这个程序只能实现主要的功能,没有界面,也没有什么操作,因能力有限,只能做到这个样子,还望老师见谅。有空的话我一定好好学习一种编程软件。实验二网络聊天窗口2.1实验目的1,进一步加深对网络底层数据传输过程的理解2,通过自己动手编写具体的代码,实现实验的要求,提高学生的编程能力3,熟悉socket编程接口,初步掌握用socket编程接口开发面向连接的网络应用程序的方法。4,熟悉socket编程接口,初步掌握用socket编程接口开发无连接的网络应用程序的方法。2.2实验原理为实现网络聊天的功能,采用WindowsSocket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。由于服务器端要保存用户信息,我们暂时利用文件保存来实现这一功能,这是为了保存较好的可移植性,在没装相应数据库的机子上也能顺利地运行。在客户端保存用户号码这一功能的实现中,采用了文件系统设计。在不同的客户间可以实现文件的传输,其原理与信息传送差不多,只不过传输的内容是文件字节流。 服务器及客户端的功能可划分为以下模块:客户端:1)登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。(由于本项目是作者09年时出于兴趣自己开始做的,所以界面中显示的是QQ2009)用用户名字登录。密码都默认为123其中,点击界面上的“注册新账号”会出现下图:在里面填写相应的名字和密码即可注册,当然服务器也要开启相应的端口,如下:2)界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。本界面中左边和右边都是截图所得,这些按钮没有实际功能,只为了模仿QQ。3)聊天功能:与好友聊天。本界面做的时候有点bug,就是聊天窗口中只有一个有个人形象展示,如上,在左边打开的窗口中没有,右边有。这一个bug有空会改过来的。4)发送文件:能发送任一文件,当然文件不能过大,否则可能会出问题。收到的图片可以正常打开5)信息提示:闪动托盘图标提示到来信息,并播放不同音乐来提示。6)其他:用户登陆成功,将保存其号码,以便下次登陆时,不必再输入而可以直接选择,显示登陆时间。服务器端:写上一个合适的端口后点击开启端口,就可以开启一个端口用来专门接收用户的连接。当有用户上线进,就会把相应的用户列在列表中。向各个客户端发布系统消息。接受来自客户端的各种信息并分别处理。1)登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就将在线用户发给该用户,并将该用户的状态发给各在线用户。同时在服务器端显示出来。2)聊天信息:转发给消息指定的用户。3)申请信息:自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。4)用户下线:将此用户下线消息发给各客户端,并改写用户在服务器端的状态。 2.3实验具体实现1、服务器端:服务器端启动时,先初始化服务端界面,之后开启一个端口用来监听客户端的连接:ChatServer.java文件里面:publicvoidsetUpServer(){try{System.out.println(port);//创建服务端套接字server=new.ServerSocket(port);MakeLog.writeLog("成功创建了一个套接字","ChatServer");//进入一个循环来等待客户端while(true){if(server!=null){.Socketclient=server.accept();//开一个线程ServerThreadnewThread=newServerThread(client);MakeLog.writeLog("已经创建一个线程连接.客户端地址:"+client.getRemoteSocketAddress(),"ChatServer");listSock.add(client);//启动线程newThread.start();}}}catch(Exceptione){e.printStackTrace();MakeLog.writeError(e.getMessage(),"ChatServer");}}然后,当有一个客户端连接上来的时候,就开启一个线程分配给该用户,用来管理该用户的连接及一些相关的操作。(其它知识点与本实验无关,这里就不再写了,下面看客户端)2、客户端:客户端一启动时,先构造出登陆界面,当点击登陆按钮时,先做一下简单的判断,看是否账号或密码为空,当它们都合法的时候就进入下一步:/***对登陆按钮作出回应*/publicvoidreact(){if(null!=tf_name.getText()||null!=tf_psw.getText()){name=tf_name.getText().trim();psw=tf_psw.getText().trim();System.out.println("name:"+name+"psw:"+psw);//创建一个连接,连接服务器connServer(serverIp,port);ClientMng.manage(client);//登陆if(ClientMng.logon(name,psw)){ClientThreadthreadCl=newClientThread();threadCl.start();}else{javax.swing.JOptionPane.showMessageDialog(jf,"登陆失败!!用户名已登陆或密码或用户名错误!");}}else{javax.swing.JOptionPane.showMessageDialog(null,"对不起,用户名和密码不能为空!!");kk=0;}jf.dispose();//最后把登陆界面关掉。}分析代码。先用客户端内置的预设的服务器地址和端口进行socket连接信尝试,连接成功时,客户端马上给服务器发送相关的用户名和密码,服务器验证通过的时候会向客户端返回一条确认信息,客户端如果接到该确认信息说明已经登陆成功了,他们就有了一个永久性的连接,直到其中的一方关闭连接为止。其实在这过程中,还有一些环节:/***登陆用的函数*@paramname:登陆用户名*@parampsw:登陆密码*@return:是否登陆成功,true登陆成功,false登陆失败*/publicstaticbooleanlogon(Stringname,Stringpsw){myName=name;StringnamePsw;if(clientSock!=null){namePsw=name+"#"+psw;sendMsg(namePsw,"system");//发送用户名和密码try{msg=readPackage();if(msg.equals("系统说:对不起,您的用户名可能为空或未注册或已登陆!!")){//javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),//"对不起,您的用户名可能为空或未注册或已登陆!!");returnfalse;}if(msg.equals("系统说:登陆失败!!密码错误!")){javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),"登陆失败!!密码错误!");returnfalse;}sendMsg("OK!","system");msg=readPackage();sendMsg("OK!","system");//接收服务器发过来的在线用户列表names=readPackage();//处理服务器刚发过来的在线用户列表if(names!=null&&!names.equals("")){String[]s=names.split("说:");String[]allName=s[1].split("#");for(inti=0;iif(!allName[i].equals("")&&allName[i]!=null&&!exists(allName[i])){listUser.add(allName[i]);}}}//发送一条消息告诉服务器,是否需要它发送分组信息过来if(needToSendTeamInfo()){sendMsg("发过来","system");//接收服务器发过来的分组信息并保存//msg=readPackage();SaveFileAfterRecievingTeamInfo();}else{sendMsg("不用发","system");initial();}}catch(Exceptionef){ef.printStackTrace();}returntrue;}returntrue;}当客户端发送了用户名和密码之后,如果收到的信息是:“对不起,您的用户名可能为空或未注册或已登陆!!”则说明重复登陆,登陆失败。如果收到的信息是:“登陆失败!!密码错误!”则说明是密码错误,当然也有可能是不存在这个用户。收到的信息如果是其它的情况,则登陆成功,这时,双方还会再各发条“OK”信息来确认双方的连接并协调步伐。之后,客户端会判断本地是否已经有相关的列表信息,如果有,则会直接读取本地好友列表信息,如果没有的话,会请求服务器发送相关的好友列表。收到好友列表后,再解析,并构建成一棵树,显示在界面的列表项中。客户端有一个工具类,里面有一个读取消息并分解消息的方法:/***按协议来读数据,包括XX说:*@return:读包结果*@throwsIOException*/publicstaticStringreadPackage()throwsIOException{//开始读数据if(dins!
if(data[i][j].dis>0)/*如果两个节点之间有路径*/
Communication(j,i);/*将i号节点的路由表发送给j号节点*/
1.4.2设计思路
程序先定义了一个路由表——RoutNodedata[ROUTNUM][ROUTNUM],路由表的初始信息存储在文件中,程序运行是先调用函数InitData(FILE*pfile)从文件中读取路由表的初始信息,然后输出初始路由表的信息,Communication(intrecv,intsend)函数主要是向邻近节点发送自己的路由表信息,Exchange()函数则根据新路由表信息更新自己的路由表。
当所有的路由表节点都更新一遍后,整个路由表更新完毕。
1.5实验结果分析
1.5.1结果截图
1.5.2结果分析
路由表初始信息从文件读取,根据距离向量路由算法系统自动完成路由表的更新操作,最后任意输入两个路由表接点,则可得出两接点之间的最短路径。
1.6实验心得体会
实验是对我们应用知识的考察,通过它我们能更加了解自己的能力。
这次的实验是网络课实验中最简单的一次,但我做得一点都不好,还没有写软件的概念和思想,程序也写得不好,还没有再实验课上完成的,是后来到寝室才完成的,没有通过老师的检查,幸亏我们的老师心地善良,说不用检查也可以通过。
这个程序只能实现主要的功能,没有界面,也没有什么操作,因能力有限,只能做到这个样子,还望老师见谅。
有空的话我一定好好学习一种编程软件。
实验二网络聊天窗口
2.1实验目的
1,进一步加深对网络底层数据传输过程的理解
2,通过自己动手编写具体的代码,实现实验的要求,提高学生的编程能力
3,熟悉socket编程接口,初步掌握用socket编程接口开发面向连接的网络应用程序的方法。
4,熟悉socket编程接口,初步掌握用socket编程接口开发无连接的网络应用程序的方法。
2.2实验原理
为实现网络聊天的功能,采用WindowsSocket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。
由于服务器端要保存用户信息,我们暂时利用文件保存来实现这一功能,这是为了保存较好的可移植性,在没装相应数据库的机子上也能顺利地运行。
在客户端保存用户号码这一功能的实现中,采用了文件系统设计。
在不同的客户间可以实现文件的传输,其原理与信息传送差不多,只不过传输的内容是文件字节流。
服务器及客户端的功能可划分为以下模块:
客户端:
1)登陆功能:
建立与服务器的连接并登陆,能显示登陆错误信息。
(由于本项目是作者09年时出于兴趣自己开始做的,所以界面中显示的是QQ2009)
用用户名字登录。
密码都默认为123
其中,点击界面上的“注册新账号”会出现下图:
在里面填写相应的名字和密码即可注册,当然服务器也要开启相应的端口,如下:
2)界面显示:
将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。
本界面中左边和右边都是截图所得,这些按钮没有实际功能,只为了模仿QQ。
3)聊天功能:
与好友聊天。
本界面做的时候有点bug,就是聊天窗口中只有一个有个人形象展示,如上,在左边打开的窗口中没有,右边有。
这一个bug有空会改过来的。
4)发送文件:
能发送任一文件,当然文件不能过大,否则可能会出问题。
收到的图片可以正常打开
5)信息提示:
闪动托盘图标提示到来信息,并播放不同音乐来提示。
6)其他:
用户登陆成功,将保存其号码,以便下次登陆时,不必再输入而可以直接选择,显示登陆时间。
服务器端:
写上一个合适的端口后点击开启端口,就可以开启一个端口用来专门接收用户的连接。
当有用户上线进,就会把相应的用户列在列表中。
向各个客户端发布系统消息。
接受来自客户端的各种信息并分别处理。
1)登陆信息:
检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。
就将在线用户发给该用户,并将该用户的状态发给各在线用户。
同时在服务器端显示出来。
2)聊天信息:
转发给消息指定的用户。
3)申请信息:
自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。
4)用户下线:
将此用户下线消息发给各客户端,并改写用户在服务器端的状态。
2.3实验具体实现
1、服务器端:
服务器端启动时,先初始化服务端界面,之后开启一个端口用来监听客户端的连接:
ChatServer.java文件里面:
publicvoidsetUpServer(){
try{
System.out.println(port);
//创建服务端套接字
server=new.ServerSocket(port);
MakeLog.writeLog("成功创建了一个套接字","ChatServer");
//进入一个循环来等待客户端
while(true){
if(server!
=null){
.Socketclient=server.accept();
//开一个线程
ServerThreadnewThread=newServerThread(client);
MakeLog.writeLog("已经创建一个线程连接.客户端地址:
"
+client.getRemoteSocketAddress(),"ChatServer");
listSock.add(client);
//启动线程
newThread.start();
}catch(Exceptione){
e.printStackTrace();
MakeLog.writeError(e.getMessage(),"ChatServer");
然后,当有一个客户端连接上来的时候,就开启一个线程分配给该用户,用来管理该用户的连接及一些相关的操作。
(其它知识点与本实验无关,这里就不再写了,下面看客户端)
2、客户端:
客户端一启动时,先构造出登陆界面
,当点击登陆按钮时,先做一下简单的判断,看是否账号或密码为空,当它们都合法的时候就进入下一步:
/**
*对登陆按钮作出回应
*/
publicvoidreact(){
if(null!
=tf_name.getText()||null!
=tf_psw.getText()){
name=tf_name.getText().trim();
psw=tf_psw.getText().trim();
System.out.println("name:
"+name+"psw:
"+psw);
//创建一个连接,连接服务器
connServer(serverIp,port);
ClientMng.manage(client);
//登陆
if(ClientMng.logon(name,psw)){
ClientThreadthreadCl=newClientThread();
threadCl.start();
}else{
javax.swing.JOptionPane.showMessageDialog(jf,"登陆失败!
!
用户名已登陆或密码或用户名错误!
");
javax.swing.JOptionPane.showMessageDialog(null,
"对不起,用户名和密码不能为空!
!
kk=0;
jf.dispose();//最后把登陆界面关掉。
分析代码。
先用客户端内置的预设的服务器地址和端口进行socket连接信尝试,连接成功时,客户端马上给服务器发送相关的用户名和密码,服务器验证通过的时候会向客户端返回一条确认信息,客户端如果接到该确认信息说明已经登陆成功了,他们就有了一个永久性的连接,直到其中的一方关闭连接为止。
其实在这过程中,还有一些环节:
*登陆用的函数
*@paramname:
登陆用户名
*@parampsw:
登陆密码
*@return:
是否登陆成功,true登陆成功,false登陆失败
publicstaticbooleanlogon(Stringname,Stringpsw){
myName=name;
StringnamePsw;
if(clientSock!
namePsw=name+"#"+psw;
sendMsg(namePsw,"system");//发送用户名和密码
msg=readPackage();
if(msg.equals("系统说:
对不起,您的用户名可能为空或未注册或已登陆!
")){
//javax.swing.JOptionPane.showMessageDialog(MainClient.getFrame(),
//"对不起,您的用户名可能为空或未注册或已登陆!
returnfalse;
登陆失败!
密码错误!
javax.swing.JOptionPane.showMessageDialog(MainClient
.getFrame(),"登陆失败!
sendMsg("OK!
","system");
//接收服务器发过来的在线用户列表
names=readPackage();
//处理服务器刚发过来的在线用户列表
if(names!
=null&&!
names.equals("")){
String[]s=names.split("说:
String[]allName=s[1].split("#");
for(inti=0;iif(!allName[i].equals("")&&allName[i]!=null&&!exists(allName[i])){listUser.add(allName[i]);}}}//发送一条消息告诉服务器,是否需要它发送分组信息过来if(needToSendTeamInfo()){sendMsg("发过来","system");//接收服务器发过来的分组信息并保存//msg=readPackage();SaveFileAfterRecievingTeamInfo();}else{sendMsg("不用发","system");initial();}}catch(Exceptionef){ef.printStackTrace();}returntrue;}returntrue;}当客户端发送了用户名和密码之后,如果收到的信息是:“对不起,您的用户名可能为空或未注册或已登陆!!”则说明重复登陆,登陆失败。如果收到的信息是:“登陆失败!!密码错误!”则说明是密码错误,当然也有可能是不存在这个用户。收到的信息如果是其它的情况,则登陆成功,这时,双方还会再各发条“OK”信息来确认双方的连接并协调步伐。之后,客户端会判断本地是否已经有相关的列表信息,如果有,则会直接读取本地好友列表信息,如果没有的话,会请求服务器发送相关的好友列表。收到好友列表后,再解析,并构建成一棵树,显示在界面的列表项中。客户端有一个工具类,里面有一个读取消息并分解消息的方法:/***按协议来读数据,包括XX说:*@return:读包结果*@throwsIOException*/publicstaticStringreadPackage()throwsIOException{//开始读数据if(dins!
if(!
allName[i].equals("")&&allName[i]!
=null
&&!
exists(allName[i])){
listUser.add(allName[i]);
//发送一条消息告诉服务器,是否需要它发送分组信息过来
if(needToSendTeamInfo()){
sendMsg("发过来","system");
//接收服务器发过来的分组信息并保存
//msg=readPackage();
SaveFileAfterRecievingTeamInfo();
sendMsg("不用发","system");
initial();
}catch(Exceptionef){
ef.printStackTrace();
returntrue;
当客户端发送了用户名和密码之后,如果收到的信息是:
“对不起,您的用户名可能为空或未注册或已登陆!
”则说明重复登陆,登陆失败。
如果收到的信息是:
“登陆失败!
”则说明是密码错误,当然也有可能是不存在这个用户。
收到的信息如果是其它的情况,则登陆成功,这时,双方还会再各发条“OK”信息来确认双方的连接并协调步伐。
之后,客户端会判断本地是否已经有相关的列表信息,如果有,则会直接读取本地好友列表信息,如果没有的话,会请求服务器发送相关的好友列表。
收到好友列表后,再解析,并构建成一棵树,显示在界面的列表项中。
客户端有一个工具类,里面有一个读取消息并分解消息的方法:
*按协议来读数据,包括XX说:
*@return:
读包结果
*@throwsIOException
publicstaticStringreadPackage()throwsIOException{
//开始读数据
if(dins!
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1