您的位置:首页 > 编程语言 > Java开发

Java Socket以及界面动态加载的简单使用

2017-12-17 10:32 363 查看
    因为Java的实验最后要做一个简单的聊天室,所以需要用到socket通信,但是书上并没有涉及这方面,所以在这里把做的过程中遇到的一些问题以及在网上找到的一些解决的办法做一下记录。

    1. 创建Socket与SocketServer

        socket 的创建有很多中方法,常用的方法有:
Socket(InetAddress address, int port),Socket(String host, int port)
。前面一个是通过制定ip 地址与端口号创建一个socket,后者是通过主机名与端口号创建一个socket。比如:Socket(getByName("localhost"),1024)
,Socket("localhost",1024);

        在确定端口号的时候,如果不确定使用哪个端口号,可以使用一个循环,逐个测试:

for(int i=1024;i<65535;++i){
try {
socket = new Socket("localhost",i);
break;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
        在创建ServerSocket 的时候,我是直接将它的端口号指定为1024: serverSocket = new ServerSocket(1024);

   2. socket 通信处理

       因为在通信的时候,需要发送多条消息,所以我想要在用户注销时才关闭socket 连接,但是serversocket一般的判断是否有待接收的数据与读取数据的方法是先判断available ,之后读取的时候使用BufferedReader 判断是否read 到的为null。而如果想让server端的read读到null ,则发送端需要关闭连接才行。所以我使用一个自定义的消息结束标志EOF,用于表示此次消息发送的结束:

 首先判断是否有待取的数据:
while(inputstream.available() == 0){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

   之后从输入流中读取数据:
BufferedReader reader = new BufferedReader(new InputStreamReader(inputstream));
System.out.println("服务器:读取数据");
StringBuffer data = new StringBuffer(); //存储本次连接接收的数据
String info;
while((info = reader.readLine()) != null && !(info.equals("EOF"))){
data.append(info);
data.append("\n");
}   3. 如何关闭serversocket
      因为serversocket的accept()方法是阻塞的,所以即使使用标志位通过while判断结束也不行。所以使用ServerSocket 的setSoTimeout() 方法,为ServerSocket的accept指定时长:

while(!isShutDown){			//持续监听客户端的连接请求
try {
System.out.println("in listen");
serverSocket.setSoTimeout(2000);
Socket socket = serverSocket.accept();

System.out.println("服务器端,socket 新连接");
new ServerSend(socket,socketpool,serverUI).start();//启动服务器端通信处理线程

} catch (IOException e1) {
//				e1.printStackTrace();
}

}

不过上面的方法会抛出IO异常,需要捕获该异常,不过不影响使用。

   4. 界面的动态加载

        实现界面的动态加载,如果是增加控件,我是先将jpanel 中的控件先保存到一个ArrayList中,之后将面板清空,最后加上之前保存的控件以及新加入的控件。在之前的操作完成后,使用invalidate(),validate(),repaint() 方法更新,最后使用的那三个用来更新界面的是参考了网上的一个方法。

        下面是部分代码实现:

  ArrayList<JCheckBox> checkBoxs = new ArrayList<JCheckBox>();
JLabel tipLable = new JLabel(); //用户面板的提示文字标签
int componentcount = clientUI.getPanelUsers().getComponentCount();
for(int i=0;i<componentcount;++i){
Object obj = clientUI.getPanelUsers().getComponent(i);
if(obj instanceof JCheckBox){
checkBoxs.add((JCheckBox)obj);
}else if(obj instanceof
4000
JLabel){
tipLable = (JLabel)obj;
}
}
clientUI.getPanelUsers().removeAll(); //清除
clientUI.getPanelUsers().add(tipLable); //先增加提示文字标签
for(int i=0;i<checkBoxs.size();++i){

clientUI.getPanelUsers().add(checkBoxs.get(i));
}

System.out.println("客户端:新增用户 " + receivedData);
//在客户端界面上显示新用户进入的消息
//TODO
clientUI.getTextArea().setFont(new Font("Arial",Font.ITALIC,10));
clientUI.getTextArea().append("New User: " + receivedData + "Coming in\n");
clientUI.getTextArea().setFont(new Font("楷体",Font.PLAIN,20));
// clientUI.getTextArea().setFont(new Font());
JCheckBox jcheckBox = new JCheckBox(receivedData,false);
jcheckBox.setSize(80, 80);
clientUI.getPanelUsers().add(jcheckBox);

clientUI.getPanelUsers().invalidate();
clientUI.getPanelUsers().validate();
clientUI.getPanelUsers().repaint();       如果是删除某个控件的话,可以简单一些,直接根据条件判断需要删除哪些,之后直接使用jpanel 的remove()方法,最后使用那三个方法更新。不知道需不需要考虑删除后控件的位置问题,我使用的布局是BoxLayout,Y轴布局,没有发现问题。

参考:

解决java获取panel中所有控件的问题 - CSDN博客: http://blog.csdn.net/u012505618/article/details/50149097
怎样在JPanel中添加删除组件????????-CSDN论坛: http://bbs.csdn.net/topics/60450227
如何关闭一个正在accept的ServerSocket? - CSDN博客: http://blog.csdn.net/qiuhan/article/details/6085176
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐