西安邮电大学Socket网络编程实验报告.docx

上传人:b****6 文档编号:15774351 上传时间:2023-07-07 格式:DOCX 页数:17 大小:491.78KB
下载 相关 举报
西安邮电大学Socket网络编程实验报告.docx_第1页
第1页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第2页
第2页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第3页
第3页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第4页
第4页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第5页
第5页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第6页
第6页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第7页
第7页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第8页
第8页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第9页
第9页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第10页
第10页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第11页
第11页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第12页
第12页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第13页
第13页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第14页
第14页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第15页
第15页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第16页
第16页 / 共17页
西安邮电大学Socket网络编程实验报告.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

西安邮电大学Socket网络编程实验报告.docx

《西安邮电大学Socket网络编程实验报告.docx》由会员分享,可在线阅读,更多相关《西安邮电大学Socket网络编程实验报告.docx(17页珍藏版)》请在冰点文库上搜索。

西安邮电大学Socket网络编程实验报告.docx

西安邮电大学Socket网络编程实验报告

《高级Internet》实验报告

 

题目:

Socket网络编程

学生姓名:

班级:

学号:

指导老师:

王文浪

成绩:

 

西安邮电大学计算机学院

2015年4月27日

一、实验目的

1熟悉Socket网络编程

2熟悉CS客户机模式

3熟悉ServerSocket编写服务端

4熟悉使用多线程机制处理业务

5了解客户机之间通信方式

二、实验内容及要求

1采用CS模式,通过客户机向服务器端发送消息;

2采用Socket来实现客户机之间的网络通信;

3通过ServerSocket创建服务端来处理接受客户机请求;

4通过多线程方式来处理客户机之间的通信请求;

5实现通信的界面窗口;

6实验内容有发送私聊消息、向选中用户发送文件、用户接受文件。

三、实验过程

1确定编程语言,架构方式,实及通信的协议

编程语言:

Java;

结构方式:

CS客户机模式;

通信协议:

在过程中为每一条通信的信息设定一个type参数,标志着通信的类型;

1:

向选中用户发送私信;0:

上下线更新

-1:

下线请求2:

请求发送文件

3:

确定接收文件

2创建工程项目SuperInternet_Client(客户机)SuperInternet_Server(服务器端)

项目客户机目录结构:

项目的服务器端目录结构:

3创建登录界面ChatLogin.java

1)(客户机)实现的核心代码:

//监听登录按钮事件(登录时从配置文件中读取用户的配置信息)btnLoginButton.addActionListener(newActionListener(){

@Override

publicvoidactionPerformed(ActionEvente){

//读取配置文件

PropertiesuserProperties=newProperties();

Filefile=newFile("Userinfo.properties");

//加载配置文件的信息

LoadPropertiesUtil.loadPro(userProperties,file);

//获得输入用户名

Stringuname=textField.getText().toString();

if(file.length()!

=0){

//在配置文件中是以键值对的方式存放用户的信息,用户名(key)=密码值(value)

if(userProperties.containsKey(uname)){//配置文件中包含该用户

//获取密码框输入的用户名

Stringupass=newString(passwordField.getPassword());

//判断用户密码是否正确

if(upass.equals(userProperties.getProperty(uname))){

//创建网络连接并显示聊天窗口

System.out.println("连接成功!

!

");

try{

//创建本地网络连接,端口为8080

Socketclient=newSocket("127.0.0.1",8080);

//将登录按钮设置为不可编辑

btnLoginButton.setEnabled(false);

//登录成功,打开聊天窗口

ChatRoomchatroom=newChatRoom(uname,client);

chatroom.setVisible(true);//显示聊天窗口

setVisible(false);//隐藏登录窗口

}catch(UnknownHostExceptione1){

e1.printStackTrace();

ErrorInfoShowUtil.errorTip("连接服务器失败,请重新登录!

",contentPanel);

}catch(IOExceptione1){

e1.printStackTrace();

ErrorInfoShowUtil.errorTip("连接服务器失败,请重新登录!

",contentPanel);

}

}else{

lblPrompt.setText("您输入的密码错误!

");...后续省略

}

});

2)创建登录界面中调用的工具类

读取配置文件工具类(LoadPropertiesUtil),实现的核心代码:

publicclassLoadPropertiesUtil{

/**

*加载配置文件的信息

*@paramproperties

*@paramfile

*/

publicstaticvoidloadPro(Propertiesproperties,Filefile){

//文件不存在,创建该文件

if(!

file.exists()){

try{

file.createNewFile();

}catch(IOExceptione){

e.printStackTrace();

System.out.println("创建配置文件失败,请检查!

");

}

}

//加载配置文件的信息

try{

properties.load(newFileInputStream(file));

}catch(FileNotFoundExceptione){

e.printStackTrace();

}catch(IOExceptione){

e.printStackTrace();

}

}

}

错误信息窗口工具类(ErrorInfoShowUtil.java),实现核心代码:

/**

*显示错误连接错误提示框

*@authorXiyouJackielin

*

*/

publicclassErrorInfoShowUtil{

publicstaticvoiderrorTip(StringerrorInfo,JPanelcontentPanel){

JOptionPane.showMessageDialog(contentPanel,

errorInfo,"ErrorMessage",JOptionPane.ERROR_MESSAGE);

}

}

3)编写服务器端ChatServer.java,接收客户机的请求连接,并返回当前在线人数:

服务器端中的静态区初始化监听连接端口及在线人数集合变量

/**

*服务器端,将听客户端请求并处理请求

*@authorXiyouJackielin

*

*/

publicclassChatServer{

//创建服务器端的socket

privatestaticServerSocketserverSocket;

//创建集合存放在线的用户

privatestaticHashMaponlines;

//创建静态块区,初始化相应的数据,只要创建一次

static{

try{

serverSocket=newServerSocket(8080);

onlines=newHashMap();

}catch(IOExceptione){

e.printStackTrace();

}

}

......//后续代码省略(开启线程)

}

④ChatRegister.java(注册页面),实现核心代码:

1)用户输入注册的信息,首先先在配置文件中寻找是否有相同的用户名,如果存在相同的用户名,则提示用户名已经重复,重新输入;

2)验证用户输入的信息,如果两次密码输入不一致,则提示密码错误;

3)用户输入注册信息验证通过后,打开配置文件Userinfo.properties,将注册信息保存至配置文件中;

@Override

publicvoidactionPerformed(ActionEvente){

PropertiesuserProperties=newProperties();

Filefile=newFile("Userinfo.properties");

LoadPropertiesUtil.loadPro(userProperties,file);

Stringuname=textField.getText().toString();

Stringupass=newString(passwordField.getPassword());

StringconfirmPass=newString(confirmpasswordField.getPassword());

//判断配置文件中是否存在该用户

if(uname.length()!

=0){

if(userProperties.containsKey("uname")){

lblPrompt.setText("该用户名已经存在!

");.....//后续省略}

编写保存用户注册信息方法,核心实现代码:

privatevoidsaveUserinfo(PropertiesuserProperties,Filefile,

Stringuname,Stringupass,StringconfirmPass){

if(upass.equals(confirmPass)){

if(upass.length()!

=0){

//以uname为键,以upass为值,保存到配置文件中

userProperties.setProperty(uname,upass);

try{

//将userProperties中的属性列表(键和值)方式写入输出流

userProperties.store(newFileOutputStream(file),

"Copyright(c)XiyouJackielin");

}catch(FileNotFoundExceptione){

e.printStackTrace();

}catch(IOExceptione){

e.printStackTrace();

}

//注册完之后将注册按钮设置为不可操作

btnRegisterButton.setEnabled(false);

//返回登录界面

ChatLoginframe=newChatLogin();

frame.setVisible(true);

setVisible(false);......//后续代码省略

4编写聊天窗口(ChatRoom.java)实现客户机之间的聊天功能

在聊天窗口中编写子线程类并开启,用于接收服务器返回的信息并显示出来;

0:

更新在线用户列表

case0:

{

//更新列表

onlines.clear();

//从服务器读取到当前的在线用户

HashSetclients=chatBean.getClients();

Iteratorit=clients.iterator();

while(it.hasNext()){

Stringele=it.next();

if(uname.equals(ele)){

onlines.add(ele+"(我)");

}else{

onlines.add(ele);

}

}

//这里通过渲染器渲染用户列表

abstractListModel=newOnlinesUserListModel(onlines);

list.setModel(abstractListModel);

......//后续代码省略

-1:

户下线;在客户机用户下线直接return结束当前窗口;

1:

私信

case1:

{//私聊

Stringinfo=chatBean.getCurrentTime()+""+chatBean.getName()

+"对"+chatBean.getClients()+"说:

\r\n";

//如果信息中包含我的名字,则将其换成昵称'我'

if(info.contains(uname)){

info=info.replace(uname,"我");

}

acpMessage.play();

textArea.append(info+chatBean.getInfo()+"\r\n");

textArea.selectAll();

break;

}

2:

向用户发送文件;

思路:

由于向用户发送文件需要接受方法确定是否接收,故采用子线程的方式处理请求过程,并向服务器发送相应的结果;

3:

确定接收文件信息;

思路:

发送方向接收方发出发送文件请求后,接收方答应接收或拒收文件,响应信息由服务器转发到发送方,对相应的信息作出相应的操作。

4:

拒接接收文件的信息;

打印出接收方拒绝接收文件的信息;

5服务器端响应处理业务

0:

更新上下线核心代码

//创建服务器端的封装信息类ChatBean,并将响应的信息发送给客户机

ChatBeanserverUplineBean=newChatBean();

serverUplineBean.setType(0);//处理的是0:

上下线更新

//设置服务器端返回信息(通知所有用户xx上线了)

serverUplineBean.setInfo(chatBean.getCurrentTime()+""

+chatBean.getName()+"上线了");

//通知所有用户有人上线

HashSetonlineUserSet=newHashSet();

//遍历在线用户onlines得到用户名的Set集合

SetonlineUserName=newHashSet();

onlineUserName=onlines.keySet();

//将用户名添加到在线用户集合中

onlineUserSet.addAll(onlineUserName);

//封装服务器端的ChatBean类

serverUplineBean.setClients(onlineUserSet);

//调用发送给全部在线用户方法

sendAll(serverUplineBean);

-1:

处理用户下线

//设置下线显示的消息

ChatBeanserverDownlineBean=newChatBean();

serverDownlineBean.setInfo(chatBean.getCurrentTime()+""

+chatBean.getName()+""+"下线了");

System.out.println(chatBean.getName());

serverDownlineBean.setType(0);

HashSetonLineUserSet=newHashSet();

onLineUserSet.addAll(onlines.keySet());

serverDownlineBean.setClients(onLineUserSet);

//将下线消息告知所有在线的用户

sendAll(serverDownlineBean);

return;//由于用户是下线,这里返回结束服务器为该类创建的业务处理线程

1:

发送私信消息

//创建服务器的ChatBean对象用于封装自己返回给客户机的消息

ChatBeanserverMessageBean=newChatBean();

serverMessageBean.setType

(1);

serverMessageBean.setClients(chatBean.getClients());//发送的用户

serverMessageBean.setInfo(chatBean.getInfo());

serverMessageBean.setName(chatBean.getName());serverMessageBean.setCurrentTime(chatBean.getCurrentTime());

//向指定的用户发送消息

sendMessage(serverMessageBean);

break;

2:

接收文件请求

//创建服务器的ChatBean对象用于封装处理用户发送文件的事务返回给客户机处理的信息

ChatBeanserverSendFileBean=newChatBean();

Stringinfo=chatBean.getCurrentTime()+""+chatBean.getName()

+"向您传送文件,是否接收文件";

serverSendFileBean.setType

(2);

serverSendFileBean.setClients(chatBean.getClients());//设置被选中的用户

serverSendFileBean.setFileName(chatBean.getFileName());//文件名称

serverSendFileBean.setSize(chatBean.getSize());//文件大小

serverSendFileBean.setInfo(info);

serverSendFileBean.setName(chatBean.getName());//文件的来源serverSendFileBean.setCurrentTime(chatBean.getCurrentTime());//设置发送的时间

//向选中的用户发送数据

sendMessage(serverSendFileBean);

break;

3:

确认接收文件信息

//创建服务器的ChatBean用于封装接收方反馈给发送方的信息

ChatBeanconfirmReceiveFielInfo=newChatBean();

confirmReceiveFielInfo.setType(3);confirmReceiveFielInfo.setClients(chatBean.getClients());//文件发送者confirmReceiveFielInfo.setSelectedTo(chatBean.getSelectedTo());//文件接收者confirmReceiveFielInfo.setFileName(chatBean.getFileName());//文件名称

confirmReceiveFielInfo.setIp(chatBean.getIp());//接收方的ip地址

confirmReceiveFielInfo.setPort(chatBean.getPort());//接收方的端口

confirmReceiveFielInfo.setName(chatBean.getName());//接收方的客户名称confirmReceiveFielInfo.setCurrentTime(chatBean.getCurrentTime());//发送时间

//通知文件发送方,接收方以确定接收文件,可以开始发送文件请求

sendMessage(confirmReceiveFielInfo);

break;

4.接收方拒绝接收文件

ChatBeanserverRefuseBean=newChatBean();

serverRefuseBean.setType(4);

serverRefuseBean.setClients(chatBean.getClients());//文件发送方serverRefuseBean.setSelectedTo(chatBean.getSelectedTo());//文件接收方

serverRefuseBean.setFileName(chatBean.getFileName());

serverRefuseBean.setInfo(chatBean.getInfo());//拒接消息

serverRefuseBean.setName(chatBean.getName());//接收客户名称

serverRefuseBean.setName(chatBean.getCurrentTime());//拒接时间

sendMessage(serverRefuseBean);

break;

四、测试结果

发送信息测试:

 

发送文件测试:

五、实验总结

这次实验过程中,我更加熟悉了使用Socket网络通信编程,同时在实验中,首先我们应该设计好通过的协议,即通信遵循的方式,再动手实现通过过程。

在实现过程中碰到了找不到

服务器发送的输入流,及socket关闭异常,经过查找错误,发现了程序中存在了以下的问题,并设计了解决的方案:

“没有创建获取当前的用户的输出流,使用的是全局的输出流,此时将得到的数据发送出去后,客户机接受到输出流数据,并且正在将其中的数据读取出来,但是服务器关闭了该类,导致客户机找不到流报错。

同时当前的链接对象也被关闭,导致了所有的窗口都一起关闭了,所以这里应注意要多创建一个输出流,用于存放更新后的用户列表”。

同时在这次实验过程中,实验过程中通过查找api使用List列表中的getSelcetedValuesList()方法,但是编译环境中找不到,最后发现是编译环境使用的jre版本太老,该函数只有在jre7之后采用,因此编程过程中应将api与编译环境统一,以免发生错误。

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

当前位置:首页 > 幼儿教育 > 幼儿读物

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

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