本来这次作业我是想搞个图形界面的,然而现实情况是我把题意理解错了,于是乎失去了最初的兴致,还是把程序变成了功能正确但是“UI”不友好的console了,但是不管怎么样,前期的图形界面的开发还是很有收获的,毕竟讲真,想要把Java搞得有形有色的也是很不容易的,借助可视化的插件windowsBuilder,这个过程还是既exciting 又tiring的。

好吧 ,然而图形界面已经成为了历史,现在来说说这个功能正确的console 吧

我也是刚知道的Eclipse里面是可以跑好多个程序的,只要你的一个.java文件中有public static void main,他就能给你一个窗口,让你跑起来。只不过这些窗口堆叠在一起,需要自行选择不同的窗口进行IO操作。

总的思路是采用c/s的方式,client借助socket完成向server的发送和接受两个工作,当然了,为了体现出真实情况下的双工的特点,发送和接受是需要开两个线程的,也就是说,一个用户需要自己管理两个线程。server则相对来讲比较复杂,因为这里面涉及到了调度,server需要有发送消息给在线client的线程(这个线程要做的事情就是只要有消息就要把消息发到所有的用户的窗口),以及接受client发来的消息的线程(这个线程要做的事情就是将接收到的消息全部交给发送消息的线程,于是这两个线程之间的通信问题也是实现上的一个关键~),为了使得所有的用户消息是同步的,server需要管理一个用户线程的列表,用以实现用户的行为的控制,于是乎这就要求只要有用户请求连接服务器,服务器就要为用户新建一个线程,那么client 和server 之间靠什么来进行联系呢,那就是我们的socket了。

 import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket; public class Client extends Thread{ private static String serverIp = "127.0.0.1";
private static int serverPort = 8001; private Socket clientsSocket; //plays key role
private PrintWriter pw; // for send data
private BufferedReader br; // for receive data public Client(){
try {
clientsSocket = new Socket(serverIp, serverPort);
pw = new PrintWriter(clientsSocket.getOutputStream(),true);
br = new BufferedReader(new InputStreamReader(clientsSocket.getInputStream()));
new readServer(); while(true){
br = new BufferedReader(new InputStreamReader(System.in));
String input = br.readLine();
//System.out.println("this is the input :" + input);
pw.println(input);
}
} catch (Exception e) {
e.printStackTrace();
}
} class readServer extends Thread{
private BufferedReader reader; public readServer(){
try {
reader = new BufferedReader(new InputStreamReader(clientsSocket.getInputStream()));
start();
} catch (Exception e) {
e.printStackTrace();
}
} public void run(){
try {
while(true){
String content = reader.readLine();
if(content.equals("bye Client")){
break;
}
else {
System.out.println(content);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} public static void main(String[] args) throws Exception{
new Client();
}
}

Client codes

 import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.LinkedList; public class Server { private static int port = 8001;
private static boolean prit = false;
private static ArrayList<String> userList = new ArrayList<>();
private static LinkedList<String> messageList = new LinkedList<>();
private static ArrayList<ServerThread> threadsList = new ArrayList<>(); private ServerSocket serverSocket; public Server(){
try {
serverSocket = new ServerSocket(port);
new PrintClient(); while(true){
Socket socket = serverSocket.accept();
new ServerThread(socket);
}
} catch (Exception e) {
e.printStackTrace();
}
} class PrintClient extends Thread{
public PrintClient(){
start();
} public void run(){
while(true){
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
if (prit == true){
String msg = messageList.getFirst();
//System.out.println("prepare to sent to Clent");
for (ServerThread sThread : threadsList){
sThread.sendMessage(msg);
}
synchronized (messageList) {
messageList.removeFirst();
}
prit = messageList.size() > 0 ? true : false;
}
}
}
} class ServerThread extends Thread{
private Socket client;
private PrintWriter pw;
private BufferedReader br;
private String user; public ServerThread(Socket socket){
try {
client = socket;
pw = new PrintWriter(client.getOutputStream(),true);
br = new BufferedReader(new InputStreamReader(client.getInputStream()));
br.readLine(); pw.println("connect success input your name ~");
start();
} catch (Exception e) {
e.printStackTrace();
}
} public void pushMessage(String msg){
synchronized (messageList) {
messageList.add(msg);
}
prit = true;
} public void sendMessage(String msg){
pw.println(msg);
} public void run(){
try {
int first = 1;
String msg = br.readLine();
while(!msg.equals("bye")){
if (first == 1){
user = msg;
userList.add(user);
threadsList.add(this);
pw.println(user + " hello you can chat now ");
this.pushMessage("Client <" + user + "> " + "join in ~");
//System.out.println("the prit is " + prit);
first--;
}
else {
this.pushMessage("Client<" + user + "> "+ "say :" + msg);
//System.out.println("the prit is " + prit + " " + messageList.size());
}
msg = br.readLine();
//System.out.println(msg);
}
pw.println("bye Client");
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
client.close();
} catch (Exception e2) {
e2.printStackTrace();
}
threadsList.remove(this);
userList.remove(user);
pushMessage(user + " leave ~");
}
}
} public static void main(String[] srgs) throws Exception{
new Server();
}
}

Server codes

在这里注意一个问题,server端的PrintClient线程在run的过程中一定要有sleep的过程,否则会因为一开始的prit设置为false而在一直在while(true)的死循环中得不到更新,也就是说线程的同步出了错,从而会出现客户端无法收到信息的错误。还有一点要注意的是作为良好的编程习惯需要注意多个线程公用的变量要注意互斥操作,防止出现多线程中的“magic bugs”。同步与互斥,真是线程进程调度中的老大难啊,每次编程都要小心处理这两个问题,尽量避免不必要的错误。

Java Socket 多线程聊天室的更多相关文章

  1. java Socket多线程聊天程序

    参考JAVA 通过 Socket 实现 TCP 编程 参考java Socket多线程聊天程序(适合初学者) 以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包 ...

  2. [置顶] Chat Room:基于JAVA Socket的聊天室设计

    d0304 更新功能实现 d0312 更新部分图片&UI设计部分 d0318 更新功能实现 d1222 实现添加好友功能.实现注册功能.修改大量BUG github:https://githu ...

  3. 【C++】基于socket的多线程聊天室(控制台版)

    以前学习socket网络编程和多线程编程的时候写的一个练手程序 聊天室基本功能: 1.用户管理:登录,注册,登出,修改用户名,修改密码 2.聊天室功能:群聊,私聊,获取在线用户列表,获取所有用户列表 ...

  4. TCP多线程聊天室

    TCP协议,一个服务器(ServerSocket)只服务于一个客户端(Socket),那么可以通过ServerSocket+Thread的方式,实现一个服务器服务于多个客户端. 多线程服务器实现原理— ...

  5. Java实现简易聊天室

    Java实现简易聊天室 在学习<Java从入门到精通>这本书,网络通信,基于TCP实现的简易聊天室,我这里对书中的代码略做了修改,做个记录. 这里先放一下运行效果图,代码放在最后. 运行效 ...

  6. Socket.IO聊天室~简单实用

    小编心语:大家过完圣诞准备迎元旦吧~小编在这里预祝大家元旦快乐!!这一次要分享的东西小编也不是很懂啊,总之小编把它拿出来是觉地比较稀奇,而且程序也没有那么难,是一个比较简单的程序,大家可以多多试试~ ...

  7. java socket 多线程网络传输多个文件

    http://blog.csdn.net/njchenyi/article/details/9072845 java socket 多线程网络传输多个文件 2013-06-10 21:26 3596人 ...

  8. java基于socket公共聊天室的实现

    项目:一个公共聊天室功能的实现,实现了登录聊天,保存聊天记录等功能. 一.实现代码 1.客户端 ChatClient.java import java.io.BufferedReader; impor ...

  9. [Java小程序]聊天室——Socket和ServerSocket的使用

    这段小代码是因为担任Java助教给刚学习Java的本科大二的小学弟小学妹们指导,他们的实验作业就是编写一个Java聊天室客户端和服务器,为了避免出纰漏,自己事先写了一下. 客户端Ui代码: packa ...

随机推荐

  1. 洛谷 P1144 最短路计数

    传送门:https://www.luogu.org/problemnew/show/P1144 这虽然是一道普及+的题,然而我发现我现在还没做过,这也就直接导致我今天模拟T2只杠了个暴力分…… 那这道 ...

  2. 对比flash与ajax哪个好?

    Ajax的优势: (1)可搜索性 普通的文本网页会更有利于SEO.文本内容是搜索引擎容易检索的,而繁琐的swf字节码却是搜索引擎不愿触及的.虽然Google等一些大型的搜索引擎可以检索SWF内部的内容 ...

  3. OpenCV——模板匹配

    minMaxLoc函数: void minMaxLoc( const Mat& src, double* minVal, double* maxVal=0, Point* minLoc=0, ...

  4. odoo开发历史订单需求整体思路

    第一步:找到客户对应页面,并找到他所下过的销售订单,用数据库语句查出所有数据,并去除重复数据,显示在前端, sql="select DISTINCT t2.product_id as pro ...

  5. 用pyinstaller把python代码打包成exe可执行文件

    优点: 1. pyinstaller 是跨平台的可以用在linux和windows系统上 2. 操作非常简单,几个命令就搞定了,这个比py2exe容易用多了 缺点: 1. 打包后的体积过大,因为要带p ...

  6. FAT32文件系统学习(2) —— FAT表

    1.题外话 在继续本文学习FAT32文件系统之前,先来插入一点别的话题.我们都知道U盘有一个属性是容量,就拿笔者的U盘为例,笔者手上的U盘是金士顿的DataTraveler G3 4GB的一个U盘.电 ...

  7. scala学习——(1)scala基础(上)

    scala> val x = 1 x: Int = 1 一.值与变量 值(val):赋值后不可变 val值名称:类型 = XXX 变量(var):赋值后可以改变  var变量名称:类型 = XX ...

  8. ES6 箭头函数易出错细节

    箭头函数表达式的语法比函数表达式更短,并且没有自己的this,arguments,super或 new.target. 箭头函数基本语法 (参数1, 参数2, -, 参数N) => { 函数声明 ...

  9. 设计模式 笔记 享元模式 Flyweight

    //---------------------------15/04/20---------------------------- //Flyweight 享元模式------对象结构型模式 /* 1 ...

  10. Android几行代码实现监听微信聊天

    原创作品,转载请注明出处,尊重别人的劳动果实. 2017.2.7更新: *现在适配微信版本更加容易了,只需要替换一个Recourse-ID即可 *可以知道对方发的是小视频还是语音,并获取秒数. *可以 ...