JSE综合练习(1)----网络聊天系统--基于TCP协议的群聊系统

     如果你经过了一段时间的JavaSE学习,对面向对象、流与文件、多线程、网络、GUI等有所了解,那么你可以试着做几个综合性的程序练练手.

     首先,模仿别人的思路和代码;然后,独立设计完成;在此基础之上,使自己的代码逐步完善、功能不断强大——这就是一个总结与升华的过程,是学习遭遇瓶颈之后的必要阶段。

     在这里笔者会把自己练习的项目源代码、注释、开发工具、相关知识、经验等分享给大家,希望可以为大家提供帮助,也希望可以获得大家的批评与指导。

     爱Java,爱Share。i java,i,share.

     这里实现了命令行界面的C/S聊天系统,一共涉及到4个类,
     在服务器端,每个Socket对应一个线程,实现每个连接的用户发送的消息向所有客户广播一边的功能。
     在客户端,可以读取数据并将其在控制台打印出来,可以发送数据广播给连接服务器的每位用户。

     笔者开发环境:

      jdk-8u40-windows-i586

      Windows Server 2003

      Notepad++

      测试时请注意包名!


1.服务器端主程序

package project_2.chatUtil.v1.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/*
 * 服务器端的ChatServer
 * 创建ServertSocket监听的主类
 * */
public class ChatServer 
{
	public static int count=1;
	//创建保存所有的客户Socket的ArryList并将其包装成线程安全的
	public static List<Socket> socketList=Collections.synchronizedList(new ArrayList<Socket>());
	//本程序的服务端口
	public static final int SERVER_PORT=51289;
	//本程序所在的主机
	public static final String SERVER_HOST="127.0.0.1";
	//主方法
	public static void main(String[] args) throws IOException
	{
		//ServerSocket对象监听本机的SERVER_PORT端口
		ServerSocket server=new ServerSocket(SERVER_PORT);
		System.out.println("服务器启动............");
		//采用循环监听
		while(true)
		{
			//accept方法会一直阻塞线程,直到有Socket连接,才会执行下面的代码
			Socket socket=server.accept();
			//把连接进来的Socket存入集合
			socketList.add(socket);
			//每当连接成功一个Socket,就启动一个ServerThread为其服务
			new Thread(new ServerThread(socket)).start();
		}
	}
}
2.服务器端线程类

package project_2.chatUtil.v1.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import javax.print.PrintService;
 //负责每个Socket通信的线程类
public class ServerThread implements Runnable
{
	//定义当前线程所服务的Socket
	Socket socket=null;
	//该Socket所对应的输入流
	BufferedReader br=null;
	//构造方法,初始化当前线程的Socket和输入流
	public ServerThread(Socket socket) throws IOException
	{
		this.socket=socket;
		//通过包装,获取带缓冲的字符输入流
		br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
	}
	//获取客户端数据的方法
	private String readFromClient()
	{
		try
		{
			return br.readLine();
		}
		// 如果捕捉到异常,则表示该客户已经离开
		catch (IOException e) 
		{
			//从集合中删除此客户
			ChatServer.socketList.remove(socket);
		}
		return null;
	}
	@Override
	public void run() 
	{
		try 
		{
			String content=null;
			System.out.println("开启一条新的服务线程!!");
			//采用循环,不断从Socket读取客户发送来的数据
			while((content=readFromClient())!=null)
			{
				for(Socket s : ChatServer.socketList)
				{
					//获取此Socket的输出流
					PrintStream ps=new PrintStream(s.getOutputStream());
					//向此Socket输出广播的消息
					ps.println(content);
				}
			}
		} 
		catch (IOException e) 
		{
			System.out.println("服务器端消息广播异常!");
		}
	}

}

3.客户端主程序

package project_2.chatUtil.v1.client;

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

import project_2.chatUtil.v1.server.ChatServer;

/**
 * 客户端
 */
public class ChatClient 
{
	public static void main(String[] args) 
	throws UnknownHostException, IOException
	{
		//创建连接到服务器的Socket
		Socket s=new Socket(ChatServer.SERVER_HOST,ChatServer.SERVER_PORT);
		//客户端启动客户端线程不断读取服务器发来的数据
		new Thread(new ClientThread(s)).start();
		//获取该Socket对应的输出流
		PrintStream ps=new PrintStream(s.getOutputStream());
		String line=null;
		//不断读取键盘输入
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入您的用户名");
		String userName="用户 [NAME:"+br.readLine()+",ID:"+System.currentTimeMillis()+"] 说:\t";
		System.out.println("下面就开始广播消息吧!如需推出,请输入: @EXIT$ ");
		while((line=br.readLine())!=null)
		{
			//将客户向键盘输入的内容不断写入Socket的输出流
			ps.println(userName+line);
			if(line.endsWith("@EXIT$"))
			{
				System.out.println("拜拜!");
				System.exit(1);
			}
		}
	}
}

4.客户端线程类

package project_2.chatUtil.v1.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/*客户端线程类
 * 负责读取数据并将其在控制台打印出来*/
public class ClientThread implements Runnable 
{
	//该线程负责处理的Socket
	Socket socket=null;
	//该线程负责处理的Socket对应的输入流
	BufferedReader br=null;
	public ClientThread(Socket socket) throws IOException
	{
		this.socket=socket;
		//通过包装,获取带缓冲的字符输入流
		br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
	}
	@Override
	public void run() 
	{
		try 
		{
			//用于存放读取的内容
			String content=null;
			//采用循环,不断读取Socket输入流中的内容
			while((content=br.readLine())!=null)
			{
				System.out.println(content);
			}
		} 
		catch (IOException e)
		{
			System.out.println("客户端读取数据异常!");
		}

	}

}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值