基于GUI的简单聊天室02

服务器端

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

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

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

  1 /**
  2  * 相比01,加进了线程内部类,解决多个客户端连接时,服务器无法全部响应的问题。
  3  * @author Administrator
  4  *
  5  */
  6
  7 import java.io.DataInputStream;
  8 import java.io.DataOutputStream;
  9 import java.io.EOFException;
 10 import java.io.IOException;
 11 import java.net.BindException;
 12 import java.net.ServerSocket;
 13 import java.net.Socket;
 14 import java.util.ArrayList;
 15 import java.util.List;
 16
 17 public class ChatSever02 {
 18     // 布尔类型变量表示服务器是否开着
 19     boolean started = false;
 20
 21     ServerSocket ss = null;
 22
 23     List<Client> clients  = new ArrayList<Client>();
 24
 25     public static void main(String[] args) {
 26             new ChatSever02().start();
 27     }
 28
 29     public void start() {
 30         try {
 31             // 建立服务端,8888为端口号
 32             ss = new ServerSocket(8888);
 33             started = true;
 34         }
 35         catch (BindException e) {
 36             System.out.println("Socket has been used !");
 37             System.out.println("请重启服务器 !");
 38             System.exit(0);
 39         }catch (IOException e) {
 40             e.printStackTrace();
 41         }
 42         // 服务器开启后,started变为true
 43         try {
 44             // 接受客户端的连接
 45             while (started) {
 46                 Socket s = ss.accept();
 47                 //构造Client对象
 48                 Client c = new Client(s);
 49                 clients.add(c);
 50                 System.out.println("一个客户连接");
 51                 //启动线程
 52                 new Thread(c).start();
 53             }
 54         }  catch (Exception e) {
 55              e.printStackTrace();
 56         } finally {
 57                 try {
 58                     ss.close();
 59                 } catch (IOException e) {
 60                     e.printStackTrace();
 61                 }
 62         }
 63     }
 64
 65
 66     /**
 67      * 建立线程内部类
 68      */
 69     class Client implements Runnable{
 70
 71         //要保有自己的Socket属性
 72         private Socket s = null;
 73
 74         //自己的数据输入流
 75         private DataInputStream dis = null;
 76
 77         private DataOutputStream dos = null;
 78
 79         private boolean bConnected = false ;
 80
 81         //采用构造方法,把Socket属性传进来
 82         public Client(Socket s) {
 83             //赋值给s
 84             this.s = s ;
 85             //将dis初始化
 86             try {
 87                 dis = new DataInputStream(s.getInputStream());
 88                 dos = new DataOutputStream(s.getOutputStream());
 89                 //连接成功后,bConnected 变为true
 90                 bConnected = true ;
 91             } catch (IOException e) {
 92                 e.printStackTrace();
 93             }
 94         }
 95
 96         /**
 97          * 发送信息的方法
 98          */
 99         public void send(String str) {
100             try {
101                 dos.writeUTF(str);
102 System.out.println(str);
103             } catch (IOException e) {
104                 e.printStackTrace();
105             }
106         }
107         @Override
108         public void run() {
109                 try {
110                     //while循环范围过大, 导致过一直报错;
111                     while (bConnected) {
112                         String str = dis.readUTF ();
113 //System.out.println(str);
114                         //发送信息
115                         for(int i = 0;i < clients.size(); i++) {
116                             Client c = clients.get(i);
117                             c.send(str);
118 //System.out.println(str);
119                         }
120
121                         /*利用迭代器
122                         for(Iterator it = clients.iterator();it.hasNext();) {
123                             Client c = it.next();
124                             c.send(str);
125                         }
126                         */
127                         /*利用迭代器第二版本
128                         Iterator<Client> it = clients.iterator();
129                         while(it.hasNext()) {
130                             Client c = it.next();
131                             c.send(str);
132                         }
133                         */
134                     }
135                 }catch (EOFException e) {
136
137                     System.out.println("Client Close !");
138                 }catch (IOException e) {
139                     e.printStackTrace();
140                 }finally {
141                         try {
142                             if(dis != null) dis.close(); //再设置dis = null;
143                             if(dos != null) dis.close();
144                             if(s != null) s.close();
145                         } catch (IOException e) {
146                             e.printStackTrace();
147                         }
148                 }
149
150         }
151     }
152 }

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

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();
                }
        }
    }
}

原文地址:https://www.cnblogs.com/happyeven/p/10765854.html

时间: 2024-08-08 16:31:29

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

基于GUI的简单聊天室01

运用了Socket编程,gui,流的读入和写出,线程控制等 思路: 1.首先是在客户端中先建立好聊天的GUI 2.建立服务器端,设置好端口号(用SocketServer),其中需要两个boolean变量来分别表示服务器是否已经开启和是否有客户端连接进来, 利用while循环来让服务器在开启的情况下不断接收客户端的信息.利用DataOutputStream来进行通讯 3.客户端连接服务器(Socket) 首先是客户端的类 1 import java.awt.BorderLayout; 2 impo

Flask基于websocket的简单聊天室

1.安装gevent-websocket pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ gevent-websocket 2.chat.py文件内容如下: from flask import Flask,request,render_template import json from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import

基于Twisted的简单聊天室

实现了私聊,公聊.用户名密码存在redis.为了拓展,做了简单的模块. #coding=utf8 from twisted.internet import reactor, defer from twisted.protocols.basic import LineReceiver from twisted.internet.protocol import Factory, Protocol, ServerFactory import redis class Server(ServerFacto

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

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

C#实例之简单聊天室(状态管理)

前言        状态管理是在同一页或不同页的多个请求发生时,维护状态和页信息的过程.因为Web应用程序的通信协议使用了无状态的HTTP协议,所以当客户端请求页面时,ASP.NET服务器端都会重新生成一个网页实例.此时,旧网页的任务完成,旧网页的实例也随之消失.这种无状态,意味着客户端用户在浏览器中的一些状态或是对数据的一些修改都将丢失. 为了弥补这种基于web应用程序的固有限制,ASP.NET提供了多种用于管理状态的功能. 简单聊天室 这里运用System.Web命名空间的那些管理状态的类,

基于flask的网页聊天室(二)

基于flask的网页聊天室(二) 前言 接上一次的内容继续完善,今天完成的内容不是很多,只是简单的用户注册登录,内容具体如下 具体内容 这次要加入与数据哭交互的操作,所以首先要建立相关表结构,这里使用flask-sqlalchemy来辅助创建 首先修改之前的init文件为: from flask import Flask from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() from web_chatroom.models impor

Python Socket 简单聊天室2

上篇文章写了一个简单的单线程的一问一答的简单聊天室.这次我们使用SocketServer模块搭建一个多线程异步的聊天室. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # -*- coding:utf-8 -*- import SocketServer class  mysocketclass(SocketServer.BaseRequestHandler):     def handle(self):         client_inform

ASP.NET 使用application和session对象写的简单聊天室程序

ASP.Net中有两个重要的对象,一个是application对象,一个是session对象. Application:记录应用程序参数的对象,该对象用于共享应用程序级信息. Session:记录浏览器端的变量对象,用来存储跨网页程序程序的变量或者对象. 说实话,写了快一年的asp.net,application对象还真没怎么用过.看了看书,根据这两个对象的特性写了一个简单的聊天室程序.真的是非常的简陋. 我的思路是,有两个页面Default页和ChatRoom页,页面布局如图: Default

基于Socket的Android聊天室

1        基于Socket的Android聊天室 Socket通信是网络通信中最常用的技术之一,通过Socket建立的可靠连接,可以让多个终端与服务器保持通信,最典型的应用是建立一个多人聊天程序.本实例使用ServerSocket建立聊天服务器.将服务器端所有的通讯线程保存到一个集合当中,当有用户发来数据,则转发给所有用户,实现聊天室效果.Android端通过使用Socket建立客户端链接,并且在AsyncTask中执行网络读写的任务,将用户输入的内容发送到服务器,并接收服务器发来的数据