服务器端

与上一篇相比,加进了线程内部类,解决多个客户端连接时,服务器无法全部响应的问题。

利用List集合来装载客户端的对象。

还需要注意全局变量的应用。

 /**
* 相比01,加进了线程内部类,解决多个客户端连接时,服务器无法全部响应的问题。
* @author Administrator
*
*/ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List; public class ChatSever02 {
// 布尔类型变量表示服务器是否开着
boolean started = false; ServerSocket ss = null; List<Client> clients = new ArrayList<Client>(); public static void main(String[] args) {
new ChatSever02().start();
} public void start() {
try {
// 建立服务端,8888为端口号
ss = new ServerSocket(8888);
started = true;
}
catch (BindException e) {
System.out.println("Socket has been used !");
System.out.println("请重启服务器 !");
System.exit(0);
}catch (IOException e) {
e.printStackTrace();
}
// 服务器开启后,started变为true
try {
// 接受客户端的连接
while (started) {
Socket s = ss.accept();
//构造Client对象
Client c = new Client(s);
clients.add(c);
System.out.println("一个客户连接");
//启动线程
new Thread(c).start();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* 建立线程内部类
*/
class Client implements Runnable{ //要保有自己的Socket属性
private Socket s = null; //自己的数据输入流
private DataInputStream dis = null; private DataOutputStream dos = null; private boolean bConnected = false ; //采用构造方法,把Socket属性传进来
public Client(Socket s) {
//赋值给s
this.s = s ;
//将dis初始化
try {
dis = new DataInputStream(s.getInputStream());
dos = new DataOutputStream(s.getOutputStream());
//连接成功后,bConnected 变为true
bConnected = true ;
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 发送信息的方法
*/
public void send(String str) {
try {
dos.writeUTF(str);
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
//while循环范围过大, 导致过一直报错;
while (bConnected) {
String str = dis.readUTF ();
//System.out.println(str);
//发送信息
for(int i = 0;i < clients.size(); i++) {
Client c = clients.get(i);
c.send(str);
//System.out.println(str);
} /*利用迭代器
for(Iterator it = clients.iterator();it.hasNext();) {
Client c = it.next();
c.send(str);
}
*/
/*利用迭代器第二版本
Iterator<Client> it = clients.iterator();
while(it.hasNext()) {
Client c = it.next();
c.send(str);
}
*/
}
}catch (EOFException e) { System.out.println("Client Close !");
}catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(dis != null) dis.close(); //再设置dis = null;
if(dos != null) dis.close();
if(s != null) s.close();
} catch (IOException e) {
e.printStackTrace();
}
} }
}
}

客户端也只是多了线程类来接收信息

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException; import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField; /**
* 完成图形界面
* @author Administrator
*
*/
public class ChatClient extends JFrame{
JTextField jTextField = new JTextField(); JTextArea jTextArea = new JTextArea(); Socket s;
//表示是否连上
private boolean bConnected = false; DataOutputStream dos; DataInputStream dis = null; public static void main(String[] args) {
new ChatClient().launchFrame();
} public void launchFrame() {
setLocation(200, 150);
this.setSize(450, 450);
this.add(jTextArea,BorderLayout.NORTH);
this.add(jTextField,BorderLayout.SOUTH);
jTextField.addActionListener(new TFListener());
//pack();
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
disConnect();
System.exit(0);
}
});; setVisible(true);
connect();
new Thread(new RecvThread()).start();
} /**
* 建立连接的方法
* @throws IOException
* @throws UnknownHostException
*/
public void connect() {
try {
s = new Socket("127.0.0.1",8888);
//连接好后初始化
dos = new DataOutputStream(s.getOutputStream());
dis = new DataInputStream(s.getInputStream());
System.out.println("连接成功");
bConnected = true;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 断开连接,关闭资源的方法
*/
public void disConnect() {
try {
dos.close();
dis.close();
s.close();
} catch (IOException e1) {
e1.printStackTrace();
} } /**
* 内部类,实现监听
* 将文本框中的输入打印到文本域中
*
*/ private class TFListener implements ActionListener{ @Override
public void actionPerformed(ActionEvent e) {
String content = jTextField.getText().trim();
//jTextArea.setText(content);
jTextField.setText("");
//将文本发送到服务器
try {
//System.out.println(s);
System.out.println(content);
dos.writeUTF(content);
dos.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
} } /**
* 线程类,用于接受信息
*
*/
private class RecvThread implements Runnable{ @Override
public void run() {
try {
while(bConnected) {
String str = dis.readUTF();
//System.out.println(str);
jTextArea.setText(jTextArea.getText() + str +" ");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

基于GUI的简单聊天室02的更多相关文章

  1. 基于GUI的简单聊天室01

    运用了Socket编程,gui,流的读入和写出,线程控制等 思路: 1.首先是在客户端中先建立好聊天的GUI 2.建立服务器端,设置好端口号(用SocketServer),其中需要两个boolean变 ...

  2. 基于GUI的简单聊天室03

    上一版本,客户端关闭后会出现“socket close”异常问题,这个版本用捕捉异常来解决,实际上只是把异常输出的语句改为用户退出之类,并没真正解决 服务器类 package Chat03; /** ...

  3. C#基于Socket的简单聊天室实践

    序:实现一个基于Socket的简易的聊天室,实现的思路如下: 程序的结构:多个客户端+一个服务端,客户端都是向服务端发送消息,然后服务端转发给所有的客户端,这样形成一个简单的聊天室功能. 实现的细节: ...

  4. Netty 系列八(基于 WebSocket 的简单聊天室).

    一.前言 之前写过一篇 Spring 集成 WebSocket 协议的文章 —— Spring消息之WebSocket ,所以对于 WebSocket 协议的介绍就不多说了,可以参考这篇文章.这里只做 ...

  5. Flask基于websocket的简单聊天室

    1.安装gevent-websocket pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ gevent-websocket 2.cha ...

  6. 基于springboot的websocket聊天室

    WebSocket入门 1.概述 1.1 Http #http简介 HTTP是一个应用层协议,无状态的,端口号为80.主要的版本有1.0/1.1/2.0. #http1.0/1.1/2.0 1.HTT ...

  7. 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

    基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...

  8. Python Socket 简单聊天室1

    这是第一版,最简单的,仅仅实现了通信,你收我发,我收你发而已.下篇将介绍,基于异步多线程的聊天室: 客户端: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ...

  9. 基于flask的网页聊天室(三)

    基于flask的网页聊天室(三) 前言 继续上一次的内容,今天完成了csrf防御的添加,用户头像的存储以及用户的登录状态 具体内容 首先是添加csrf的防御,为整个app添加防御: from flas ...

随机推荐

  1. luogu1049装箱问题

    装箱问题 传送门 一个箱子容量为V//容量 同时有n个物品//n个 体积&&价值 要求n个物品中任取若干个装入箱内,使箱子的剩余空间为最小// v减去价值最大 */ #include& ...

  2. requirejs概念

  3. FAST:NetMagic交换机 与 Floodlight控制器 连接实战

    设备 NetMagic 08交换机 - 1; 装有Windows 7系统的PC - 1; VMware Workstation, Ubuntu 14.04 64bit - 1; 网线 - 1; 网口转 ...

  4. DFS回溯-函数递归-xiaoz triangles

    题目:小z 的三角形 ★实验任务 三角形的第1 行有n 个由"+"和"-"组成的符号,以后每行符 号比上行少1 个,2 个同号下面是"+", ...

  5. hdu 1014 Uniform Generator 数论

    摘取于http://blog.csdn.net/kenden23/article/details/37519883: 找到规律之后本题就是水题了,不过找规律也不太容易的,证明这个规律成立更加不容易. ...

  6. nohup 与 &

    &的意思是在后台运行, 什么意思呢?  意思是说, 当你在执行 ./a.out & 的时候, 即使你用ctrl C,  那么a.out照样运行(因为对SIGINT信号免疫). 但是要注 ...

  7. json 与 string 互转

    1. json字符串转换成json对象 js: JSON.parse('{"age":"28"}') eval('(' + '{"age": ...

  8. 解决dos窗口乱码问题

    大家有没有遇到这样的情况,看着就糟心 打开dos窗口, 输入命令 chcp 936 (936表示中文编码GBK, 也可以设置其他编码), 回车一下执行.  鼠标右键 -> 属性  (关键一步): ...

  9. Symbol的控件模板

    <esriSymbols:TextSymbol x:Name="text1" Text="adadfdf"></esriSymbols:Tex ...

  10. Anton and School - 2 CodeForces - 785D (组合计数,括号匹配)

    大意: 给定括号字符串, 求多少个子序列是RSGS. RSGS定义如下: It is not empty (that is n ≠ 0). The length of the sequence is ...