Java 简易C/S结构多线程聊天室 (阻塞式)

主要实现的功能:

服务器端建立ServerSocket阻塞监听来自客户端的Socket连接,并为之开辟一个新的线程

读取来自该连接的数据,广播每一个客户端数据,这里简单地使用一个链表保存所有来自客户端的所有Socket连接

客户端连接上服务器端后主要有两个线程在工作:

主线程:不断获取键盘的输入并写入该Socket中传输给服务器

副线程:不断从服务器Socket流中读取传来的数据,打印到屏幕上。

服务器端代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.ServerSocket;
import java.util.ArrayList;
import javax.swing.JOptionPane;

public class MyServer {

	public static ArrayList<Socket> socketlist = new ArrayList<Socket>();
	private static String port ;
	public static void main(String[] args) throws IOException
	{
		//弹出一个对话框输入端口号
		port = JOptionPane.showInputDialog("input the port number: ");
		int ServerPort = new Integer(port).intValue();
		
		ServerSocket ss = new ServerSocket(ServerPort);
		System.out.println("Server is initializating...");
		while(true)
		{
			System.out.println("Server is waiting...");
			
			//此处将阻塞监听
			Socket s = ss.accept();
			System.out.println("listening from: " + s.getInetAddress());
			socketlist.add(s);
			new Thread(new ServerThread(s)).start();
		}
	}
 
}
class ServerThread implements Runnable
{
	Socket s = null;
	BufferedReader br = null;
	public ServerThread(Socket s) throws IOException
	{
		this.s = s;
		br = new BufferedReader(new InputStreamReader(s.getInputStream()));
	}
	public void run()
	{
		try
		{
			String content = null;
			while( (content = readFromClient()) != null )
			{
				//播报每个客户端数据
				for(Socket s : MyServer.socketlist)
				{
					PrintStream ps = new PrintStream(s.getOutputStream());
					ps.println(content);
				}
			}
		}
		catch (IOException io) 
		{
			io.printStackTrace();
		}
	}
	private String readFromClient()
	{
		try
		{
			return br.readLine();
		}
		catch (IOException io)
		{
			MyServer.socketlist.remove(s);
			System.out.println(s.getInetAddress() + " is disconnecting...");
		}
		return null;
	}
	
}

客户端代码:

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

public class MyClient {

	public static void main(String[] args) throws Exception
	{
		Socket s = new Socket("192.168.1.164", 30000);

		// new Thread to read content from server.
		new Thread(new ClientThread(s)).start();

		PrintStream ps = new PrintStream(s.getOutputStream());
		String line = null;
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		while((line = br.readLine()) != null)
		{
			ps.println(line);
		}
	}
}
class ClientThread implements Runnable
{
	private Socket s = null;
	BufferedReader br = null;
	public ClientThread(Socket s) throws IOException
	{
		this.s = s;
		br = new BufferedReader(new InputStreamReader(s.getInputStream()));
	}
	public void run()
	{
		try
		{
			String content = null;
			while( (content = br.readLine()) != null)
			{
				System.out.println(content);
			}
		}
		catch (IOException io)
		{
			io.printStackTrace();
		}
	}
}

后期开发:

上面程序功能很简单,没有记录客户信息,考虑添加功能如下:(多人聊天室)

客户端发来的信息必须添加特殊标识,用于区别 登陆,私聊,公聊 三种,如果是登陆,则服务器端应该有一个

Map来保存用户名和对应输出流中间的关系,用来处理用户名重复的情况,还有如果是私聊,必须知道从客户端发来消息的用户名和将要发给哪一个用户的特殊标识,考虑在输入字符串里加入特殊标识符。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值