利用TCP和多线程实现服务端和多个客户端建立实时聊天小案例

每当有一个客户端和服务端建立连接之后,服务端就会产生一个线程从而来产生一个Socket来和客户端连接

客户端会产生两个线程,一个线程是用来获取标准键盘输入流InputStream,就是通过System.in来获得,和向服务端发送消息的输出流,另外一个线程就是用来接收服务端发送来的消息,获得输入流


服务端:

package com.iotek.test;

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

public class ChatServer {

	public static void main(String[] args) throws IOException {
		ServerSocket server=new ServerSocket(8888);
		int number=1;//用来保存客户端人数
		while(true){
			Socket socket=server.accept();
			System.out.println("客户端"+number+"连接成功");
			//服务端开启一个独立的线程来对客户进行读写操作
			ServerStream runable=new ServerStream(socket, number);
			new Thread(runable).start();
			number++;
		}
	}

}

服务端线程

package com.iotek.test;

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

public class ServerStream implements Runnable {
	
	private Socket socket=null;
	private int number;
	
	public ServerStream(Socket socket,int number){
		this.socket=socket;
		this.number=number;
	}
	
	@Override
	public void run() {
		//String str=null;
		try {
			//获取和客户端连接的输入流
			BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
			//创建想该客户端发送信息的输出流
			PrintWriter pw=new PrintWriter(socket.getOutputStream(),true);
			while(true){
				String str=br.readLine();
				System.out.println("客户端"+number+": "+str);
				pw.println(str.toUpperCase());
				if(str.equals("over")){
					System.out.println("客户端"+number+"已经断开连接");
					break;
				}
				
			}
			br.close();
			pw.close();		
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

客户端:

package com.iotek.test;

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

public class ChatClint {

	public static void main(String[] args) throws UnknownHostException, IOException {
		Socket socket=new Socket("192.168.1.3",8888);
		ClintStream runable=new ClintStream(socket);
		ClintStreamInput input=new ClintStreamInput(socket);
		new Thread(runable).start();
		new Thread(input).start();
		
	}

}

客户端用来获取标准键盘输入流:

package com.iotek.test;

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

public class ClintStream implements Runnable {
	
	private Socket socket=null;
	
	public ClintStream(Socket socket) {
		this.socket=socket;
	}

	@Override
	public void run() {
		//String str=null;
		try {
			//客户端获取键盘输入流
			BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
			//客户端获取可以向服务端发送消息的输出流
			PrintWriter pw=new PrintWriter(socket.getOutputStream(),true);
			while(true){
					String str=br.readLine();
				pw.println(str);
				if(str.equals("over")){
					break;
				}
			}
			br.close();
			pw.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

客户端用来获取和服务端连接的输入流:

package com.iotek.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
//该类用于读取服务器端向客户端发来的信息
public class ClintStreamInput implements Runnable {
	
	private Socket socket=null;
	
	public ClintStreamInput(Socket socket) {
		this.socket=socket;
	}

	@Override
	public void run() {
		String str=null;
		try {
			BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
			while(true){
				str=reader.readLine();
				if(str.equalsIgnoreCase("over")){
					break;
				}
				System.out.println(str);
			}
			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

其实我们查看PrintWriter的源代码可以发现,PrintWriter的底层就是Writer,它的println()方法,其实就是调用了Writer的write()方法,只不多多了换行而已



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值