基于GUI的简单聊天室02
服务器端
与上一篇相比,加进了线程内部类,解决多个客户端连接时,服务器无法全部响应的问题。
利用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的更多相关文章
- 基于GUI的简单聊天室01
运用了Socket编程,gui,流的读入和写出,线程控制等 思路: 1.首先是在客户端中先建立好聊天的GUI 2.建立服务器端,设置好端口号(用SocketServer),其中需要两个boolean变 ...
- 基于GUI的简单聊天室03
上一版本,客户端关闭后会出现“socket close”异常问题,这个版本用捕捉异常来解决,实际上只是把异常输出的语句改为用户退出之类,并没真正解决 服务器类 package Chat03; /** ...
- C#基于Socket的简单聊天室实践
序:实现一个基于Socket的简易的聊天室,实现的思路如下: 程序的结构:多个客户端+一个服务端,客户端都是向服务端发送消息,然后服务端转发给所有的客户端,这样形成一个简单的聊天室功能. 实现的细节: ...
- Netty 系列八(基于 WebSocket 的简单聊天室).
一.前言 之前写过一篇 Spring 集成 WebSocket 协议的文章 —— Spring消息之WebSocket ,所以对于 WebSocket 协议的介绍就不多说了,可以参考这篇文章.这里只做 ...
- Flask基于websocket的简单聊天室
1.安装gevent-websocket pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ gevent-websocket 2.cha ...
- 基于springboot的websocket聊天室
WebSocket入门 1.概述 1.1 Http #http简介 HTTP是一个应用层协议,无状态的,端口号为80.主要的版本有1.0/1.1/2.0. #http1.0/1.1/2.0 1.HTT ...
- 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。
基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...
- Python Socket 简单聊天室1
这是第一版,最简单的,仅仅实现了通信,你收我发,我收你发而已.下篇将介绍,基于异步多线程的聊天室: 客户端: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ...
- 基于flask的网页聊天室(三)
基于flask的网页聊天室(三) 前言 继续上一次的内容,今天完成了csrf防御的添加,用户头像的存储以及用户的登录状态 具体内容 首先是添加csrf的防御,为整个app添加防御: from flas ...
随机推荐
- hash入门
如果你已经确保自己的hash技巧已经入门,那么请左转这篇博文 首先介绍一下hash? 事实上是一种叫做蛤丝的病毒 以下讲到的hash都是OI中最常用到的hash方法:进制哈希 做法: 首先设一个进制数 ...
- 【Coursera】Security Introduction -Eighth Week(1)
Security Introduction People With Bad Intent 今天,Bob 向 Alice 发送了一条 "Hello,Allice!" 的信息,他们希望 ...
- Python的替换函数——replace(),strip(),和re.sub()
在Python中常用的三个"替换"函数是strip(),replace()和re.sub(),下面来讲讲这三个函数的用法. 一.replace() 基本用法:对象.replace( ...
- BZOJ 1189 【HNOI2007】 紧急疏散evacuate
题目链接:紧急疏散 这薄脊题我代码不知不觉就写长了…… 这道题二分答案显然,然后用最大流\(check\)即可.设当前二分的答案为\(x\),那么把每扇门拆成\(x\)个点,第\(i\)个代表在第\( ...
- Could not find a package configuration file provided by 'ecl_threads' ,.................couldn't find required component 'ecl_threads'
sudo apt-get install ros-kinetic-ecl-threads
- selenium-firefox-headless
from selenium import webdriver import time fireFoxOptions = webdriver.FirefoxOptions() fireFoxOption ...
- Codeforces 101487E - Enter The Dragon
101487E - Enter The Dragon 思路:做的时候两个地方理解错了,第一个事我以为龙吸了水,水就干了,其实龙是在下雨之前吸的,下雨时湖水又满了,所以湖水永远不会干:第二个是以为只要找 ...
- React生命周期钩子
最近的工作都很忙,所以很少完整的时间可以用来总结和回顾知识点,今天就趁着是周末,我准备在这里复习和回顾一下React的基础.工作中主要用的vue比较多,在工作中使用React也已经是一年前了,当时用的 ...
- ubuntu , 笔记本合上盖子时不关机的方法。
实测ubuntu 14.04 好使 1) 编辑 /etc/systemd/logind.conf 2) 找到 HandleLidSwitch 设置,去掉行头注释#,然后改成下面这样 HandleLid ...
- 如何将新项目添加到github仓库中?只需简单几步~即可实现
问题描述:新建了一个项目,如何将其设置为git项目?如何关联到github上的仓库? 只需简单几步,但前提是需要已经安装好了git,并且有github账户 本文使用IntelliJ IDEA 其他编辑 ...