ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java网络编程:TCP实现群聊功能代码

2020-03-15 21:41:13  阅读:271  来源: 互联网

标签:Java java TCP client private import msg 群聊 客户端


Java网络编程:TCP实现群聊功能代码

实现的功能:群聊

具体操作流程的大致思路:

某个客户端发送消息,服务器将该消息转发给其余客户端(除了自己)。
代码一共分两个端(服务器和客户端(其中客户端一共3个代码)),所以一共四个代码(下面有显示代码)。

客户端代码:(三个代码,其中Send和Receive可以看做被被Client使用创建的,分开封装而已)
服务器代码:(一个代码)

(1)Send类的代码:

package chat3;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * 作用:被MutiClient类用到,是客户端用来发送消息的
 * 具体操作是:客户端读取控制台消息--写入到client的输出流
 * @author Administrator
 *
 */
public class Send implements Runnable {
	private BufferedReader console;
	private DataOutputStream dos;
	private Socket client;
	private boolean isRunning;
	private String name;
	public Send(Socket client,String name) {
		this.client=client;
		this.name=name;
		console=new BufferedReader(new InputStreamReader(System.in));
		try {
			dos=new DataOutputStream(client.getOutputStream());
			
			sendMsg(name);//发送名字
			isRunning=true;
		} catch (IOException e) {
			System.out.println("客户端的send构造器有问题");
			this.release();
		}
	}
	
	@Override
	public void run() {
		while(isRunning) {
			//客户端读取控制台消息--写入到client的输出流
			String msg=ConsoleMsg();
			if(!msg.equals("")) {
				sendMsg(msg);
			}
			
		}
	}
	private String ConsoleMsg() {//先读取控制台的内容
		String msg="";
		try {
			msg=console.readLine();
		} catch (IOException e) {
			System.out.println("客户端的ConsoleMsg有问题");
			this.release();
		}
		return msg;
		
	}
	private void sendMsg(String msg) {//再写入到客户端的输出流里
		try {
			dos.writeUTF(msg);
			dos.flush();//这个一定不能忘记啦
		} catch (IOException e) {
			System.out.println("客户端的sendMsg有问题");
			this.release();
		}
	}
	//释放资源
	private void release() {//内部类的使用
		this.isRunning=false;//释放资源意味着该该客户端要停下来
		Utils.close(dos,client);//自己写的一个工具类Utils
	}
}

(2)Receive类的代码:

package chat2;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;

/**
 *作用: 被MutiClient类用到,是客户端用来接收服务器反馈的消息的
 *客户端读取服务器反馈的消息,并显示输出
 * @author Administrator
 *
 */
public class Receive implements Runnable {
	private DataInputStream dis;
	private Socket client;
	private boolean isRunning;
	public Receive(Socket client) {
		this.client=client;
		isRunning=true;
		try {
			dis=new DataInputStream(client.getInputStream());
		} catch (IOException e) {
			System.out.println("客户端的Receive构造器有问题");
			release();
		}
	}
	
	@Override
	public void run() {
		while(isRunning) {
			String msg=receiveMsg();
			if(!msg.equals("")) {
				System.out.println(msg);
			}
		}
	}
	
	private String receiveMsg() {
		String msg="";
		try {
			msg=dis.readUTF();
		} catch (IOException e) {
			System.out.println("客户端的receiveMsg有问题");
			release();
		}
		return msg;
	}
	//释放资源
	private void release() {//内部类的使用
		this.isRunning=false;//释放资源意味着该该客户端要停下来
		Utils.close(dis,client);//自己写的一个工具类Utils
	}
}

(3)Client类的代码:

package chat3;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

/**注意:
 * 在线聊天室:使用容器实现群聊
 * 客户端
 * @author Administrator
 *
 */
public class Client {
	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("---------------client--------------");
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入用户名:");
		String name=br.readLine();
		//建立套接字
		Socket client=new Socket("localhost", 8983);
		
		//客户端发送消息(先读取控制台的内容,再写入到客户端的输出流里)
		new Thread(new Send(client,name)).start();
		new Thread(new Receive(client)).start();
	}
}

(4)Server类的代码:

package chat3;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList;

/**注意:
 * 在线聊天室:使用容器实现群聊
 * 服务器
 * @author Administrator
 * 需要修改和遍历数据的时候使用list会操作不方便
 * 问题:为什么加了static,在主函数里面就没错啦?
 * 
 */
public class Server {
	//CopyOnWriteArrayList和list用法一样
	private static CopyOnWriteArrayList<Channel> all=new CopyOnWriteArrayList<Channel>();
	public static void main(String[] args) throws IOException {
		System.out.println("----------server----------");
		
		//创建服务器
		ServerSocket server=new ServerSocket(8983);
		
		while(true) {
			//阻塞式等待客户端的连接
			Socket client=server.accept();
			System.out.println("一个客户端连接上。。。");
			Channel c=new Channel(client);
			all.add(c);//容器管理所有的成员
			new Thread(c).start();
		}
	}
	
	//一个客户代表一个Channel
	static class Channel implements Runnable{
		private DataInputStream dis ;
		private DataOutputStream dos;
		private Socket client;
		private boolean isRunning;//程序是否停下来的标志
		private String name;
		public Channel(Socket client) {
			this.client=client;
			try {
				dis = new DataInputStream(client.getInputStream());
				dos=new DataOutputStream(client.getOutputStream());
				isRunning=true;
				
				//获取名称
				name=receiveMsg();
				this.sendMsg(name+"同学,"+"欢迎您的到来");
				sendOther(this.name+"加入群聊天室",true);
				
			} catch (IOException e) {
				System.out.println("-----1   出问题----");//自己方便观察哪里出问题
				release();//注意:这里做了修改
			}
		}
		
		//接收消息(服务器读取客户端发过来的信息)
		private String receiveMsg() {
			String msg="";
			try {
				msg=dis.readUTF();
			} catch (IOException e) {
				System.out.println("-----receive 出问题----");//自己方便观察哪里出问题
				release();//注意:这里做了修改
			}
			return msg;
		}
		
		//发送消息(服务器反馈信息给客户端)
		private void sendMsg(String msg) {
			try {
				dos.writeUTF(msg);
				dos.flush();
			} catch (IOException e) {
				System.out.println("-----send 出问题----");//自己方便观察哪里出问题
				release();//注意:这里做了修改
			}
		}
		
		//发送消息(服务器反馈信息(其实就是服务器读取的当前客户端的消息)给其他所有的客户端(除了当前客户端)
		private void sendOther(String msg,boolean isSysMsg) {
			for(Channel other:all) {//服务器把收到的客户端的消息发给其余所有的客户端(除了当前客户端)
				if(other!=this) {
					if(isSysMsg) {
						other.sendMsg(msg);//系统消息
					}else {
						other.sendMsg(this.name+":"+msg);//群聊消息
					}
				}
			}
		}
		
		//释放资源
		private void release() {
			this.isRunning=false;//释放资源意味着该该客户端要停下来
			Utils.close(dis,dos,client);//自己写的一个工具类Utils
			all.remove(this);//当前客户端退出
			sendOther(this.name+"离开了聊天室。。。", true);
		}

		@Override
		public void run() {
			while(isRunning) {
				//流程:服务器读取客户端消息-服务器发送反馈消息给客户端-释放资源
				String msg=receiveMsg();
				//System.out.println("服务器读取到的信息为:"+msg);
				if(!msg.equals("")) {
					//sendMsg(msg);
					sendOther(msg,false);//群聊消息
				}
				
			}
			//release();//老师这里没有释放
		}
	}
}

多嘴一句,如果不会运行该代码,自行百度一下,就知道啦!!!很关键。

运行效果如下:

在这里插入图片描述
以上就是Java TCP网络编程对于群聊模式功能的简单实现,大家有什么不清楚的,欢迎留言哈(虽然我也很菜的)!!!加油!!!

标签:Java,java,TCP,client,private,import,msg,群聊,客户端
来源: https://blog.csdn.net/qiaoermeng/article/details/104886407

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有