`
icarusliu
  • 浏览: 237355 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java的一个简单聊天原型

    博客分类:
  • java
阅读更多

接触Socket没多长时间,自己想模拟实现一个聊天程序,因此写出了这个原型。因为所有这些想法都是自己单独想出来的,也没有上网查实现一个聊天的程序应当怎么弄,所以其中肯定有很多不理想的地方。本身的目的只是为了熟悉一下Socket与多线程编程,所以如果觉得程序哪不好感谢各位赐教。

1. Server.java:做为一个中转站,接收来自各个用户线程传输过来的消息,然后将其发送到相应的目的地。

 

package com.icarusliu.learn.chart.test3;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server implements Runnable {
	private ServerSocket server;

	// 服务器信息
	private static final int serverPort = 9001;// 端口是一定的

	public Server() {
		try {
			server = new ServerSocket(serverPort);// 启动服务
		} catch (IOException ex) {
			System.out.println("Server-Error:cannot init the Server!");
		}
	}

	public void run() {
		System.out.println("Server-Server started!");
		// 如果有用户请求,那么为用户配一个用户线程
		while (true) {
			try {
				Socket socket = server.accept();
				UserThread t = new UserThread(socket);
				Thread ut = new Thread(t);
				ut.start();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	/**
	 * 用户线程,每个用户线程包括一个消息,一个接受线程,一个发送线程
	 * 
	 * @author Administrator
	 * 
	 */
	class UserThread implements Runnable {
		private Message message;//共用一个消息存储
		private SendThread sendThread;//发送线程
		private ReceiveThread receiveThread;//接收线程
		private Socket socket;

		public UserThread(Socket socket) {
			this.socket = socket;
			message = new Message();
		}

		public void run() {
			System.out.println("Server-User:"
					+ socket.getInetAddress().getHostAddress() + "("
					+ socket.getPort() + ") connected!");
			receiveThread = new ReceiveThread(socket);
			Thread rt = new Thread(receiveThread);
			rt.start();

			 // 发送的socket,用连接用户的socket
			 sendThread = new SendThread();
			 Thread st = new Thread(sendThread);
			 st.start();
		}

		/**
		 * 发送线程
		 * 
		 * @author Administrator
		 * 
		 */
		class SendThread implements Runnable {
			private void sendMessage() {
				try {
					Message m = message.getMessage();
					Socket socket = new Socket(m.getToUrl(), m
							.getToPort());
					System.out.println("Server-Sending:" + m);
					ObjectOutputStream output = new ObjectOutputStream(socket
							.getOutputStream());
					
					output.writeObject(m);// 发送对象

					output.flush();
					output.close();

				} catch (IOException ex) {
					System.out.println("发送线程没有连接上!发送失败!");
					//这里表示要发送的目标客户没有连接上。因此如果没有连接上可以将这条消息保存下来等客户连接上的时候再发送过去。相当于QQ的离线消息
				}
			}

			public void run() {
				sendMessage();
			}
		}

		/**
		 * 接收线程
		 * 
		 * @author Administrator
		 * 
		 */
		class ReceiveThread implements Runnable {
			private Socket socket;

			public ReceiveThread(Socket socket) {
				this.socket = socket;
			}

			/**
			 * 接收到对象然后赋给message,再调用message上面阻塞的发送线程
			 */
			private void setMessage() {
				try {
					ObjectInputStream input = new ObjectInputStream(socket
							.getInputStream());
					Object messObject = input.readObject();
					System.out.println("Server-Receiving:" + messObject);
					if (messObject instanceof Message) {
						Message m = (Message) messObject;
						message.setMessage(m);
					}
				} catch (IOException ex) {
					ex.printStackTrace();
				} catch (ClassNotFoundException ex) {
					System.out.println("传输出现问题!");
				}
			}

			public void run() {
				if (socket != null) {
					setMessage();
				}
			}
		}
	}

	public static void main(String[] args) {
		Server s = new Server();
		Thread st = new Thread(s);
		st.start();
	}
}

 2.Client.java:客户端,通过Server中转来对其它客户端发送消息,并接受其它客户端的消息

 

package com.icarusliu.learn.chart.test3;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Client {
	//这个客户端的名称
	private String name;
	
	//服务器信息
	private final String serverUrl = "localhost";
	private final int serverPort = 9001;
	
	//客户端信息,暂只有一个客户端,后面可以改成多个这些信息应该来自于客户端
	private String clientUrl = "localhost";
	private int clientPort = 9002;
	
	private int client2Port = 9003;
	
	public Client(String name,String clientUrl,int clientPort,int client2Port){
		this.name = name;
		this.clientUrl = clientUrl;
		this.clientPort = clientPort;
		this.client2Port = client2Port;
	}
	
	public void start(){
		try{
			SendThread st = new SendThread();
			Thread t = new Thread(st);
			t.start();	
			
			ReceiveThread rt = new ReceiveThread();
			Thread rtt = new Thread(rt);
			rtt.start();			
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	
	/**
	 * 接收线程
	 * @author Administrator
	 *
	 */
	class ReceiveThread implements Runnable{		
		public void run(){
			try{
				ServerSocket ss = new ServerSocket(clientPort);
				while(true){
					Socket s = ss.accept();
					ObjectInputStream input = new ObjectInputStream(s.getInputStream());
					System.out.println(name + "-Receiving111:" + input.readObject());
					input.close();
				}
			}catch(IOException ex){
				System.out.println("接收线程初始化失败!");
			}catch(ClassNotFoundException ex){
				System.out.println("没有找到对象!");
			}
		}
	}
	
	/**
	 * 发送线程
	 * @author Administrator
	 *
	 */
	class SendThread implements Runnable{
		public void sendMessage(String message){
			try{
				System.out.println(name + "Sending:" + message);
				Socket socket = new Socket(serverUrl,serverPort);
				Message m = new Message(message,clientUrl,client2Port,clientUrl,clientPort);
				ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
				output.writeObject(m);
				output.flush();
				output.close();
			}catch(IOException ex){
				ex.printStackTrace();
			}			
		}
		
		public void run(){
			int i=3;
			while(i-->0){
				sendMessage("message from " + name + i);
				try{
					Thread.sleep(1000);
				}catch(Exception ex){
					ex.printStackTrace();
				}
			}
		}
	}
	
	public static void main(String[] args){
		Client client = new Client("client1","localhost",9002,9003);
		client.start();
		
		Client client2 = new Client("client2","localhost",9003,9002);
		client2.start();
	}
}

 3.Message.java:传递的消息对象

 

package com.icarusliu.learn.chart.test3;

import java.io.Serializable;

/**
 * 消息
 * 
 * @author Administrator
 * 
 */
class Message implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private String value;

	// 消息目的地
	private String toUrl;
	private int toPort;

	// 消息来源
	private String fromUrl;
	private int fromPort;

	public Message() {

	}

	public Message(String value, String toUrl, int toPort, String fromUrl,
			int fromPort) {
		this.value = value;
		this.toUrl = toUrl;
		this.toPort = toPort;
		this.fromPort = fromPort;
		this.fromUrl = fromUrl;
	}

	/**
	 * 设置消息 唤醒等待线程
	 * 
	 * @param message
	 */
	public synchronized void setMessage(Message message) {
		this.value = message.getValue();
		this.toUrl = message.getToUrl();
		this.toPort = message.getToPort();
		this.fromPort = message.getFromPort();
		this.fromUrl = message.getFromUrl();
		notifyAll();
	}

	/**
	 * 取得消息,如果消息为空,那么等待
	 * 
	 * @return
	 */
	public synchronized Message getMessage() {
		if (value == null || value.equals("")) {
			try {
				wait();
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
		}
		Message message = new Message(value, toUrl, toPort, fromUrl, fromPort);
		this.setNull();
		return message;
	}

	public String getToUrl() {
		return this.toUrl;
	}

	public int getToPort() {
		return this.toPort;
	}

	public String getFromUrl() {
		return this.fromUrl;
	}

	public int getFromPort() {
		return this.fromPort;
	}

	public String getValue() {
		return this.value;
	}

	public void setNull() {
		this.value = null;
	}

	public String toString() {
		return "Message:(" + this.getValue() + "-" + this.getFromUrl()
				+ this.getFromPort() + "-" + this.getToUrl() + this.getToPort()
				+ ")";
	}
}

  4.执行结果:

Server端:

 

Server-Server started!
Server-User:127.0.0.1(1179) connected!
Server-User:127.0.0.1(1178) connected!
Server-Receiving:Message:(message from client12-localhost9002-localhost9003)
Server-Receiving:Message:(message from client22-localhost9003-localhost9002)
Server-Sending:Message:(message from client22-localhost9003-localhost9002)
Server-Sending:Message:(message from client12-localhost9002-localhost9003)
Server-User:127.0.0.1(1182) connected!
Server-User:127.0.0.1(1183) connected!
Server-Receiving:Message:(message from client21-localhost9003-localhost9002)
Server-Sending:Message:(message from client21-localhost9003-localhost9002)
Server-Receiving:Message:(message from client11-localhost9002-localhost9003)
Server-Sending:Message:(message from client11-localhost9002-localhost9003)
Server-User:127.0.0.1(1186) connected!
Server-User:127.0.0.1(1187) connected!
Server-Receiving:Message:(message from client20-localhost9003-localhost9002)
Server-Receiving:Message:(message from client10-localhost9002-localhost9003)
Server-Sending:Message:(message from client20-localhost9003-localhost9002)
Server-Sending:Message:(message from client10-localhost9002-localhost9003)
Server-User:127.0.0.1(1191) connected!
Server-User:127.0.0.1(1190) connected!
Server-Receiving:Message:(message from client22-localhost9003-localhost9002)
Server-Receiving:Message:(message from client12-localhost9002-localhost9003)
Server-Sending:Message:(message from client22-localhost9003-localhost9002)
Server-Sending:Message:(message from client12-localhost9002-localhost9003)
Server-User:127.0.0.1(1195) connected!
Server-User:127.0.0.1(1194) connected!
Server-Receiving:Message:(message from client11-localhost9002-localhost9003)
Server-Sending:Message:(message from client11-localhost9002-localhost9003)
Server-Receiving:Message:(message from client21-localhost9003-localhost9002)
Server-Sending:Message:(message from client21-localhost9003-localhost9002)
Server-User:127.0.0.1(1198) connected!
Server-User:127.0.0.1(1199) connected!
Server-Receiving:Message:(message from client20-localhost9003-localhost9002)
Server-Sending:Message:(message from client20-localhost9003-localhost9002)
Server-Receiving:Message:(message from client10-localhost9002-localhost9003)
Server-Sending:Message:(message from client10-localhost9002-localhost9003)

 Client端:

 

client1Sending:message from client12
client2Sending:message from client22
client1-Receiving111:Message:(message from client22-localhost9003-localhost9002)
client2-Receiving111:Message:(message from client12-localhost9002-localhost9003)
client1Sending:message from client11
client2Sending:message from client21
client2-Receiving111:Message:(message from client11-localhost9002-localhost9003)
client1-Receiving111:Message:(message from client21-localhost9003-localhost9002)
client2Sending:message from client20
client1Sending:message from client10
client1-Receiving111:Message:(message from client20-localhost9003-localhost9002)
client2-Receiving111:Message:(message from client10-localhost9002-localhost9003)
 

 

分享到:
评论

相关推荐

    java多线程实现一个控制台聊天室

    本项目采用Java语言,利用多线程技术实现了一个简单的控制台聊天室。该聊天室具备基本的客户端与服务器端交互功能,用户可以通过控制台窗口进行文字聊天交流。 #### 二、核心功能模块 1. **服务器端**:负责接受...

    java编写的GUI简单socket聊天源码小程序

    总的来说,这个"java编写的GUI简单Socket聊天源码小程序"是一个很好的学习资源,它涵盖了Java GUI编程、Socket通信和多线程等核心概念。通过分析和理解这个源码,开发者可以加深对网络编程的理解,尤其是如何将这些...

    用Java实现简单聊天系统邹形

    在本文中,我们将深入探讨如何使用Java编程语言来构建一个简单的聊天系统原型。这个系统将为初学者提供一个良好的学习平台,了解网络编程、多线程以及Java Socket通信的基础知识。下面,我们将详细阐述实现这样一个...

    java web 开发的临时聊天窗口 并不是很完善 可以实现简单聊天

    在这个场景中,"java web 开发的临时聊天窗口" 指的可能是一个简单的在线聊天功能,允许用户通过Web浏览器进行实时交流。这个描述指出这个聊天窗口并不完善,这意味着它可能是一个基础的原型或者学习项目,而非一个...

    一个简单聊天程序

    总的来说,"一个简单聊天程序"可能涉及到网络编程、GUI设计、多线程、数据序列化等多个Java开发领域的知识点,对于初学者来说是个不错的实践项目,对于有经验的开发者则是一个快速构建原型或学习新概念的平台。

    本科毕业论文-基于JAVA的聊天系统的设计与实现

    7. **软件开发过程**:论文还提到了软件开发的过程,强调了原型法的应用,即先构建一个简单的系统原型,通过不断的测试和反馈,逐步完善和扩展系统功能,最终实现一个完整且稳定的聊天系统。 ### 结论 基于JAVA的...

    学位论文-—基于java的聊天室客户端.doc

    本文档介绍了一个基于 Java 技术的聊天室客户端的设计和实现,旨在提供一个功能强大且稳定的聊天工具。该系统采用 Java 语言开发,使用 Eclipse 作为基本开发环境,充分发挥了 Java 的面向对象、分布式、健壮性、...

    JAVA socket 通信

    在"socket_test1"这个文件中,很可能是包含了一些Socket通信的测试代码或者是一个简单的聊天室原型。通过分析和运行这个文件,可以更深入地理解如何在实际项目中应用Java Socket通信和JAIN SIP。 总的来说,Java ...

    java设计模式解释

    一个复杂的图像处理系统中,可以定义一个简单的外观接口,用于执行常见的图像处理任务,如缩放、旋转等。 #### 十一、享元模式(Flyweight) **定义:** 享元模式是一种结构型设计模式,它运用共享技术来有效地...

    简单可以直接用的聊天代码

    "简单可以直接用的聊天代码"提供了一种便捷的方式,让我们能够快速搭建一个基本的聊天室,无需从零开始编写所有底层逻辑。 这个资源可能包含了一个完整的聊天应用源代码,我们可以从中学习到以下关键知识点: 1. *...

    Java 24种设计模式

    单例模式确保一个类只有一个实例,并提供一个全局访问点。 **应用场景:** 当你希望在整个系统中只存在一个实例时,例如数据库连接、线程池等资源。 **优点:** - 确保系统中只有一个实例。 - 全局唯一性。 **...

    Java Script网页特效实例大全

    总之,"Java Script网页特效实例大全"是一个宝贵的资源,可以帮助开发者掌握JavaScript在创建动态、引人入胜的网页特效方面的应用,提升其在Web开发中的专业技能。通过学习和实践这些实例,开发者能够更好地理解和...

    以轻松的语言比喻了java的23种模式

    外观模式就像是一本简化的说明书,它提供了一个简单易用的操作指南,让你可以快速上手使用相机。通过这种方式,你不必深入研究每个细节就能享受到专业级的效果。 #### 十一、享元模式(Flyweight) 享元模式是一种...

    趣味JAVA23种设计模式

    适配器模式通过适配器类将一个接口转换为客户期望的另一个接口,实现了类之间的松耦合。 #### 桥接模式(Bridge) 桥接模式将抽象化与实现化分离,允许它们独立变化。比如,对不同的时间、场合向女孩表达问候或...

    command-line-chat-prototype:用于知识的简单命令行聊天原型

    介绍这个项目有助于理解多线程聊天开发的模式基础安装方式一 sh compilar.sh方式二在eclipse中在这个文件夹中创建一个java项目运行它运行服务器 java -cp "bin/" sockets.SocketServer运行客户端 java -cp "bin/" ...

    关于Java23种设计模式的有趣见解.

    **定义**:工厂模式是一种创建型设计模式,其中包含一个创建产品族的接口,但允许子类决定实例化哪一个类。工厂方法让类的实例化延迟到子类。 **示例**:在追求心仪女生的过程中,为了让她开心,男生可能会选择带她...

    jsp聊天室_直接能用

    【标题】"jsp聊天室_直接能用"指的是一个基于JSP技术开发的在线聊天室应用,无需数据库支持,可以直接部署并使用。...同时,对于有经验的开发者,这个聊天室也是一个快速启动原型或测试环境的便捷工具。

    关于java23种设计模式的有趣见解

    在QQ聊天中发送预先准备好的情话,就像是在使用一个预设的“情话”原型,需要时只需复制粘贴即可。这样,可以快速生成相同或相似的实例,避免了每次都从头创建新对象的繁琐过程。 #### 5. SINGLETON(单例模式) ...

    java设计模式(简化版的big java)

    工厂模式是一种简单的创建型设计模式,它提供了一个创建对象的接口,但允许子类决定实例化哪一个类。这样,工厂模式就将对象的创建过程封装起来,使得客户端无需关注对象是如何被创建的。例如,当你想要得到一个鸡翅...

Global site tag (gtag.js) - Google Analytics