基于Java socket和多线程的简易聊天小程序

本人介绍一下基于java多线程和socket实现简易聊天室的小程序。

        本程序实现的目标是,一个服务端和N个客户端可以实现互相聊天,客户端一个线程用于发送消息,另一个线程负责接收消息。服务端用N个线程进行消息发送,用N个线程进行消息接收,而且消息的接收和发送互不影响。

首先实现服务端,建立类TestThreadServer,首先实现服务端收发线程,用两个默认修饰符修饰的类实现:       

class ServerReceiveRunnable implements Runnable{
	
	private Socket s=null;
	
	public ServerReceiveRunnable(Socket s){
		this.s=s;
	}
	
	public void run() {
		// TODO Auto-generated method stub
		InputStream is=null;
		DataInputStream dis=null;
		
		try {
			while(true){
				is=s.getInputStream();
				dis=new DataInputStream(is);
				System.out.println("server received:"+dis.readUTF());
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
	
}

class ServerSendRunnable implements Runnable{
	
	private Socket s=null;
	
	public ServerSendRunnable(Socket s){
		this.s=s;
	}
	
	public void run() {
		// TODO Auto-generated method stub
		OutputStream os=null;
		DataOutputStream dos=null;
		try {
			while (true) {
				os = s.getOutputStream();
				dos = new DataOutputStream(os);
				Scanner in = new Scanner(System.in);
				String line = in.nextLine();
				dos.writeUTF(line);
			} 
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	
}



<p>这两个Runnable接口的实现类通过构造方法传入一个Socket对象,在run方法中实现Socket的输入和输出。</p><p>在TestThreadServer类的main方法中首先先开启ServerSocket,用一个永远不会自动停止的while循环(此处也可以设定一个布尔类型的成员变量来控制循环的结束)来监听客户端Socket的连接情况,一旦客户端Socket传入,则立即由服务端ServerSocket捕获并绑定在两个个线程中,一个线程负责该Socket的输入,另一个线程负责该Socket的输出:</p>

public class TestThreadServer {

	@SuppressWarnings("resource")
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		ServerSocket ss=null;
		ss=new ServerSocket(5652);
		while(true){
			Socket s=ss.accept();
			Runnable r1=new ServerReceiveRunnable(s);
			Thread t1=new Thread(r1);
			t1.start();
			
			Runnable r2=new ServerSendRunnable(s);
			Thread t2=new Thread(r2);
			t2.start();
		}
	}

}

服务端的代码到此为止,接下来看客户端的代码,客户端代码也是大同小异,同样先用两个Runnable接口的实现类来通过传入Socket实现客户端的发送与接收:

这两个Runnable接口的实现类通过构造方法传入一个Socket对象,在run方法中实现Socket的输入和输出。

在TestThreadServer类的main方法中首先先开启ServerSocket,用一个永远不会自动停止的while循环(此处也可以设定一个布尔类型的成员变量来控制循环的结束)来监听客户端Socket的连接情况,一旦客户端Socket传入,则立即由服务端ServerSocket捕获并绑定在两个个线程中,一个线程负责该Socket的输入,另一个线程负责该Socket的输出:

class ClientSendRunnable implements Runnable{
	
	private Socket s=null;
	
	public ClientSendRunnable(Socket s){
		this.s=s;
	}
	
	public void run() {
		// TODO Auto-generated method stub
		OutputStream os=null;
		DataOutputStream dos=null;
		
		try {
			while(true){
				os=s.getOutputStream();
				dos=new DataOutputStream(os);
				Scanner in=new Scanner(System.in);
				String line=in.nextLine();
				dos.writeUTF(line);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
	}
	
}


class ClientReceiveRunnable implements Runnable{
	
	private Socket s=null;
	
	public ClientReceiveRunnable(Socket s){
		this.s=s;
	}
	
	public void run() {
		// TODO Auto-generated method stub
		InputStream is=null;
		DataInputStream dis=null;
		
		try {
			while(true){
				is=s.getInputStream();
				dis=new DataInputStream(is);
				System.out.println("client received:"+dis.readUTF());
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

在客户端

这两个Runnable接口的实现类通过构造方法传入一个Socket对象,在run方法中实现Socket的输入和输出。

在TestThreadServer类的main方法中首先先开启ServerSocket,用一个永远不会自动停止的while循环(此处也可以设定一个布尔类型的成员变量来控制循环的结束)来监听客户端Socket的连接情况,一旦客户端Socket传入,则立即由服务端ServerSocket捕获并绑定在两个个线程中,一个线程负责该Socket的输入,另一个线程负责该Socket的输出:

class ClientSendRunnable implements Runnable{
	
	private Socket s=null;
	
	public ClientSendRunnable(Socket s){
		this.s=s;
	}
	
	public void run() {
		// TODO Auto-generated method stub
		OutputStream os=null;
		DataOutputStream dos=null;
		
		try {
			while(true){
				os=s.getOutputStream();
				dos=new DataOutputStream(os);
				Scanner in=new Scanner(System.in);
				String line=in.nextLine();
				dos.writeUTF(line);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
	}
	
}

class ClientReceiveRunnable implements Runnable{
	
	private Socket s=null;
	
	public ClientReceiveRunnable(Socket s){
		this.s=s;
	}
	
	public void run() {
		// TODO Auto-generated method stub
		InputStream is=null;
		DataInputStream dis=null;
		
		try {
			while(true){
				is=s.getInputStream();
				dis=new DataInputStream(is);
				System.out.println("client received:"+dis.readUTF());
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}


客户端TestThreadClient类中的main方法则开启这两个线程,实现与服务端的连接:

public class TestThreadClient {
	
	public static void main(String[] args) throws Exception{
		Socket s=null;
		
		s=new Socket("127.0.0.1",5652);
		Runnable r1=new ClientSendRunnable(s);
		Thread t1=new Thread(r1);
		t1.start();
		
		Runnable r2=new ClientReceiveRunnable(s);
		Thread t2=new Thread(r2);
		t2.start();
	}
	
}

至此,这个简单的小程序就写完了,有些缺陷,比如流没有关闭,因为一旦关闭,则Socket就会关闭,导致无法用多线程实现收发信息。

这两个Runnable接口的实现类通过构造方法传入一个Socket对象,在run方法中实现Socket的输入和输出。

在TestThreadServer类的main方法中首先先开启ServerSocket,用一个永远不会自动停止的while循环(此处也可以设定一个布尔类型的成员变量来控制循环的结束)来监听客户端Socket的连接情况,一旦客户端Socket传入,则立即由服务端ServerSocket捕获并绑定在两个个线程中,一个线程负责该Socket的输入,另一个线程负责该Socket的输出:

阅读更多
个人分类: Java
下一篇共同学习Java源码--开篇语
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭