【Java】Socket+多线程实现控制台聊天室

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827212.html

聊天室程序的结构图:

架构解释:

Server服务器相当于一个中转站,Client客户端程序传送信息到服务器,服务器再把信息分发到其他客户端上,实现即时通信。

所需技术:

1:数据传输。

服务器与客户端之间的信息传递,都通过数据通道实现,有一个客户端连接到服务器,就有一条数据通道架设于该客户端和服务器之间。

这条数据通道通过Socket来实现:每个客户端通过一个socket与服务器建立连接,这是通道的一个“端点”。而服务器端ServerSocket一旦检测到有客户端接入,accept()方法就会马上返回一个socket对象与客户端的socket对接起来,这是通道的另一个“端点”。“两点建立一条直线”,当然,这里不一定是直的(废话)。总之,一条像水管一样的通道就这样把一个客户端与服务器联系起来了。之后的事情,就是把我们要传输的数据,通过数据通道传输,如同水管运水一样,数据就是那些水。

2:持续监听。

即时聊天要求某一客户端(聊天者)敲出来的话要立刻更新到连接到该服务器上的所有客户端的界面上,这个简单,学过while循环的人应该都能立刻想到:我用一个while()语句持续地从数据通道检测数据不就成了?一旦数据通道有信息,马上把它取出来,在客户端显示就ok了。

然而!这事儿还没完。每个客户端都要保持持续接收用户输入的状态。你总不能一个客户端只发送一次信息就关闭掉了吧?

那么问题来了,又要保持持续监听服务器端传过来的信息,又要保持持续监听键盘输入,那这俩while循环到底怎么安排呢?

这里最容易犯的错误就是,用一个while循环嵌套了另一个while循环。比如下面的代码:

while ((msg1 = br.readLine()) != null) {
      System.out.println(msg1);
     while (true) {
     msg2 = re.readLine();
     pw.println(msg2);
   }

外层循环持续监听数据通道,一旦有服务器端传过来的信息,就提取出来显示到客户端。内层循环持续监听键盘输入,有则通过pw(数据通道,等下会有源码)传输给服务器。

这里错误在于,内层循环是死循环,不会停止,所以会出现客户端不停输入信息发送到服务器,然而信息却没有更新到其他的客户端去。因为客户端代码停留在内层循环,没有出去执行监听并提取数据通道信息那一部分代码。

还有一种案例,就是在客户端输入信息,却没有显示出来,狂按键盘也没见打出一个字。但是把服务器程序关闭后却又在客户端程序窗口看到一大堆刚才输入的信息。

这种错误的原因与上面相反,是监听数据通道的while循环阻塞了下一个while循环(接收键盘输入部分)的执行。代码如下:

BufferedReader br = new BufferedReader(new InputStreamReader(socket .getInputStream()));

    String msg1; 

    while ((msg1 = br.readLine()) != null) {
             System.out.println(msg1);
   }

BufferedReader re = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
    String msg2;
    while (true) {
        msg2 = re.readLine();
        pw.println(msg2);
}

上面一个while循环持续监听数据通道(服务器向客户端传送信息),保持在等待接收信息状态,导致下面的代码没有执行,所以客户端不能接收用户输入,狂敲键盘也没用。

而关闭服务器程序后,数据通道断了,就不再监听,转而运行到了下面的while循环,所以就能接收用户输入。

那么正确的姿势是怎样的呢?那就是:并行。

在一个while循环运行的同时,另一个while循环也运行。两个while循环没有先后之分。

要实现并行,就需要用到多线程技术。【多线程是啥我就不讲了,基本上能做到这个项目的人都是学了多线程再来实践的吧哈哈哈~】

正确完整代码贴出来,仅供参考。如果你是用来应付老师布置的作业的,小心和别的同学撞车-_-:

Server.java:

import java.net.*;
import java.io.*;
import java.util.*;

public class Server
{ int port;
List<Socket> clients;
ServerSocket server;
public static void main(String[] args)
{
new Server();
}
public Server()
{
try{

port=8080;
clients=new ArrayList<Socket>();
server=new ServerSocket(port);

while(true)
{
Socket socket=server.accept();
clients.add(socket);
Mythread mythread=new Mythread(socket);
mythread.start();
}

}catch(Exception ex)
{
}
}
class Mythread extends Thread
{
Socket ssocket;
private BufferedReader br;
private PrintWriter pw;
public String msg;
public Mythread(Socket s)
{
ssocket=s;
}
public void run()
{

try{
br = new BufferedReader(new InputStreamReader(ssocket.getInputStream()));
msg = "欢迎【" + ssocket.getInetAddress() + "】进入聊天室!当前聊天室有【"
+ clients.size() + "】人";

sendMsg();

while ((msg = br.readLine()) != null) {

msg = "【" + ssocket.getInetAddress() + "】说:" + msg;
sendMsg();

}
}catch(Exception ex)
{

}
}
public void sendMsg()
{
try{
System.out.println(msg);

for(int i = clients.size() - 1; i >= 0; i--)
{
pw=new PrintWriter(clients.get(i).getOutputStream(),true);
pw.println(msg);
pw.flush();
}
}catch(Exception ex)
{
}
}

}

}

Client.java:

import java.io.*;
import java.net.*;
import java.util.*;

public class Client{
public int port=8080;
Socket socket=null;

public static void main(String[] args)
{
new Client();
}

public Client()
{

try {
socket=new Socket("127.0.0.1",port);

new Cthread().start();

BufferedReader br = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
String msg1;
while ((msg1 = br.readLine()) != null) {

System.out.println(msg1);
}
}catch (Exception e) {
}
}

class Cthread extends Thread
{

public void run() {
try {

BufferedReader re = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
String msg2;

while (true) {

msg2 = re.readLine();
pw.println(msg2);
}
}catch (Exception e) {
e.printStackTrace();
}

}
}

}

老习惯,来个总结:用Socket构建数据通道(InputStream/OutputStream),用多线程同时运行两个while实现监听与更新,就是聊天室的技术所在。

(本人新手,恳请老码农们指正。感激不尽!若需要转载与交流,请于评论处留言告知我一声,谢谢)

时间: 2024-10-13 11:55:01

【Java】Socket+多线程实现控制台聊天室的相关文章

java多线程控制台聊天室(转)

用java多线程实现一个控制台聊天室,呵呵,好玩! 聊天室服务器端 Java代码   package tf.thread; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.u

Java和WebSocket开发网页聊天室

小编心语:咳咳咳,今天又是聊天室,到现在为止小编已经分享了不下两个了,这一次跟之前的又不大相同,这一次是网页聊天室,具体怎么着,还请各位看官往下看~ Java和WebSocket开发网页聊天室 一.项目简介 WebSocket是HTML5一种新的协议,它实现了浏览器与服务器全双工通信,这里就将使用WebSocket来开发网页聊天室,前端框架会使用AmazeUI,后台使用Java,编辑器使用UMEditor. 二.涉及知识点 网页前端(HTML+CSS+JS)和Java 三.软件环境 Tomcat

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

http://blog.csdn.net/njchenyi/article/details/9072845 java socket 多线程网络传输多个文件 2013-06-10 21:26 3596人阅读 评论(1) 收藏 举报  分类: JAVA(158)  由于需要研究了下用 java socket 传输文件,由于需要传输多个文件,因此,采用了多线程设计.客户端每个线程创建一个 socket 连接,每个 socket 连接负责传输一个文件,服务端的ServerSocket每次 accept

Socket编程(简易聊天室客户端/服务器编写、CocoaAsyncSocket)

Socket编程(简易聊天室客户端/服务器编写.CocoaAsyncSocket) 一.Socket 1.1 Socket简介 Socket就是为网络服务提供的一种机制.网络通信其实就是Socket间的通信,通信的两端都是Socket,数据在两个Socket间通过IO传输. 在Web服务大行其道的今天,调用Web服务的代价是高昂的,尤其是仅仅是抓取少量数据的时候尤其如此.而使用Socket,可以只传送数据本身而不用进行XML封装,大大降低数据传输的开销.Socket允许使用长连接,允许应用程序运

字节码学院之Java socket 控制台聊天室

学了个把月基础,终于写出了一个双工通信的控制台版本的聊天室了,废话不说啦,直接上代码:服务端代码 package com.zijiemaedu.socketdemo; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; /** * @author: Mr-zhang * @create: 2019-05-30 09:48 * @emall: [email

多线程+socket实现多人聊天室

最近在学习多线程的时候打算做一个简单的多线程socke聊天的程序,结果发现网上的代码都没有完整的实现功能,所以自己实现了一个demo: demo功能大致就是,有一个服务端负责信息转发,多个客户端发送消息,当一个客户端发送消息时,其他的客户端都可以接受到. 服务端: 客户端: 客户端代码: package com.cky.client; import java.io.IOException; import java.io.InputStream; import java.io.PrintWrite

网络编程(学习整理)---2--(Udp)实现简单的控制台聊天室

1.UDP协议: 总结一下,今天学习的一点知识点! UDP也是一种通信协议,常被用来与TCP协议作比较!我们知道,在发送数据包的时候使用TCP协议比UDP协议安全,那么到底安全在哪里呢?怎么理解呢! 下面我说一下我的简单理解! 由于TCP协议是一种面向连接的协议,有三次挥手通信确认机制,且数据包没有代销限制,TCP协议确保在通信双方都收到对方确认信息的前提下,才开始为通信的双方传输信息(数据包)! 这样数据包的传输可以得到安全保障!所以简单的理解为安全的!当然一旦,出现网络问题,或者一些其他意外

网络编程(学习整理)---1--实现简单的控制台聊天室

1.简单的聊天室(控制台): 功能实现: 客户端和服务端的信息交流: 2.牵扯到的知识点: 这个我大概说一下,详细后面见代码! 1) 网络通讯的三要素 1. IP 2. 端口号. 3. 协议   2) InetAddress(IP类) 常用的方法: getLocalHost(); 获取本机的IP地址 getByName("IP或者主机名") 根据一个IP地址的字符串形式或者是一个主机名生成一个IP地址对象. (用于获取别人的IP地址对象) getHostAddress() 返回一个IP

使用socket.io打造公共聊天室

最近的计算机网络课上老师开始讲socket,tcp相关的知识,当时脑袋里就蹦出一个想法,那就是打造一个聊天室.实现方式也挺多的,常见的可以用C++或者Java进行socket编程来构建这么一个聊天室.当然,我毫不犹豫选择了node来写,node有一个名叫socket.io的框架已经很完善的封装了socket相关API,所以无论是学习还是使用都是非常容易上手的,在这里强烈推荐!demo已经做好并放到我的个人网站了,大家可以试试,挺好玩的. 进去试试 ->   http://www.yinxiang