服务器端

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

利用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. Linq 对List的一些操作

    代码: public class Person { public int ID { get; set; } public string Name { get; set; } public int Ag ...

  2. Codeforces Round #528 div1

    完了,看来上一次的flag要应验了,我大概是真的要掉成pupil了吧.. A - Connect Three 这个就是找到x的中间值,y的中间值,然后切一下,然后把所有的点挂到这条边上.但是我做的还是 ...

  3. 2、extract-text-webpack-plugin提取Sass编译的Css

    cnpm install css-loader --save-dev    //css-loader 是将css打包进js cnpm install style-loader --save-dev   ...

  4. 手机常用meta标签-有注释

    <!-- 设置字体编码 --> <meta charset="UTF-8"> <!-- 视图窗口,移动端特属的标签. --> <meta ...

  5. Git operate

    新建远程分支和删除 https://www.jianshu.com/p/ea1dab2de419 使用git branch -a查看所有分支 远程先开好分支然后拉到本地 git checkout -b ...

  6. preg_match

    $baseUrl = request()->baseUrl(); if (!preg_match('/admin.php/',$baseUrl)) { $this->redirect('/ ...

  7. NetCat教程

    NetCat by Jian Lee 简介 使用 隐藏命令行参数 正/反向域名解析 参数详解 案例 监听端口(制作蜜罐) 端口扫描 ftp 服务器 两台服务器文件校验 使用注意 简介 使用 最简单的使 ...

  8. Python 爬虫-Requests库入门

    2017-07-25 10:38:30 response = requests.get(url, params=None, **kwargs) url : 拟获取页面的url链接∙ params :  ...

  9. spring boot: @Entity @Repository一个简单的数据读存储读取

    spring boot: @Entity @Repository一个简单的数据读存储读取 创建了一个实体类. 如何持久化呢?1.使用@Entity进行实体类的持久化操作,当JPA检测到我们的实体类当中 ...

  10. win7创建 VirtualBox COM 对象失败。 应用程序现在将终止。 Callee RC: E_NOINTERFACE (0x80004002)

    win7创建 VirtualBox COM 对象失败.  应用程序现在将终止.    Callee RC: E_NOINTERFACE (0x80004002) 启动VirtualBox提示这个错误, ...