服务器端

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

利用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. Facebook广告API系列 Business Manager

    Facebook广告API系列 Business Manager Business Manager,是个很牛叉的东西,有多牛叉呢? 因为facebook已经越来越商业化了,上面的每个账号,页面,往往都 ...

  2. Qt5.2+opencv2.4.9配置安装过程

    Qt5.2+Opencv2.4.9的安装与配置 安装环境 Win10系统 Qt5.2.0 Opencv2.4.9 1. 安装Qt5.2.0 安装在D:\Qt\5.2.0文件夹(记为A文件夹) Qt下载 ...

  3. 05_Flume_timestamp interceptor实践

    1.目标场景 2.Flume Agent配置 # specify agent,source,sink,channel a1.sources = r1 a1.sinks = k1 a1.channels ...

  4. HDU 2874 Connections between cities(LCA离线算法实现)

    http://acm.hdu.edu.cn/showproblem.php?pid=2874 题意: 求两个城市之间的距离. 思路: LCA题,注意原图可能不连通. 如果不了解离线算法的话,可以看我之 ...

  5. HDU 3549 Flow Problem(最大流模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=3549 刚接触网络流,感觉有点难啊,只好先拿几道基础的模板题来练练手. 最大流的模板题. #include< ...

  6. mysql 对比两个表的一致性

    -- A和B两个表 数据是否一致select 自定义 from A left join B on A.id = B.id where B.id is null 注释:这样查询的结果是A表中有而B表中没 ...

  7. MVC ---- EF的安装于卸载

    先卸载EF:Uninstall-Package EntityFramework -Force 在安装EF5.0:Install-Package EntityFramework –Version 5.0 ...

  8. rostopic 命令

    rostopic bw display bandwidth used by topic// rostopic delay display delay for topic which has heade ...

  9. jstl中<c:forEach>的用法

    在JSP的开发中,迭代是经常要使用到的操作.例如,逐行的显示查询的结果等.在早期的JSP中,通常使用Scriptlets来实现Iterator或者Enumeration对象的迭代输出.现在,通过JST ...

  10. mapStateToProps,mapDispatchToProps的使用姿势

    本文作者:IMWeb 黄qiong 原文出处:IMWeb社区 未经同意,禁止转载 前言 刚接触redux的时候,发现大家对mapDispatchToProps使用有几种方法,而且都跑通了,本文来介绍下 ...