通信-聊天室(JAVA)

如果之前没有接触过通信方面的知识,请移步https://blog.csdn.net/S_G_G/article/details/113482830

在有了初步尝试之后,我们可以试着写一个聊天室。

其实只多了一个问题要解决:并发。

我们的基本思路是:

        1、服务器端接受客户部分另写一个继承于Thread类的Receiver类来实现。

        2、服务器端,对于每个客户,都建立一个NetConn对象(也继承于Thread类)来实现与客户的通信。 

        3、每个客户端也建立一个NetConn对象(与服务器端的NetConn对象不同)来实现与服务器端的通信。

这样就能保证服务器端接受客户和传输数据不冲突,客户之间与服务器通信也不冲突。

由于服务器端发送数据时要发送给所有客户,所以我用一个ArrayList来存所有的NetConn对象,并且将这个ArrayList专门放在ClientList类中。

用swing的JTextField组件来实现编辑和获取要发送的消息的功能。

用swing的JTextArea组件来实现显示接收到的消息的功能。

服务器端的流程图如下:

                                  

服务器端Server类(主类)代码

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.ServerSocket;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class Server{
	private ServerSocket ss;
	private JTextArea ta;
	
	private Server(){		//服务器端界面初始化
		JFrame jf=new JFrame("聊天室-服务器");
		jf.setSize(500, 500);
		JButton btn=new JButton("发送");
		jf.add(btn);
		JTextField tf=new JTextField(20);
		ta=new JTextArea(20,30);
		jf.add(tf);
		jf.add(ta);
		jf.setDefaultCloseOperation(3);
		jf.setLayout(new FlowLayout());
		jf.setVisible(true);
		btn.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				String msg=tf.getText();
				ClientList.send(msg);
				tf.setText("");
			}
		});
		this.work();
	}
	
	private void work(){			//核心代码
		try {					
			ss=new ServerSocket(9999);
			Receiver r=new Receiver(ss,ta);
			r.start();
		} catch (IOException e) {e.printStackTrace();}
		
	}
	
	public static void main(String[] args){
		Server s1=new Server();
	}
	
}

服务器端Receiver类代码

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

import javax.swing.JTextArea;

public class Receiver extends Thread{
	private ServerSocket ss;
	private JTextArea ta;
	
	Receiver(ServerSocket s,JTextArea t){
		ss=s;
		ta=t;
	}
	
	public void run(){
		while(true){		//不停地接收客户,建立NetConn对象并加入ArrayList中
			try {
				Socket client=ss.accept();
				NetConn nc=new NetConn(client,ta);
				nc.start();
				ClientList.list.add(nc);
			}
			catch (IOException e) {	e.printStackTrace();}
		}
	}
	
}

服务器端NetConn类代码

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

import javax.swing.JTextArea;

public class NetConn extends Thread{
	private Socket client;
	private JTextArea ta;
	private DataInputStream dis;
	private DataOutputStream dos;
	
	NetConn(Socket s,JTextArea t){
		client=s;
		ta=t;
	}
	
	public void send(String msg){		//向该客户发送消息
		byte[] data=msg.getBytes();
		int l=data.length;
		try {
			dos.writeInt(l);
			dos.write(data);
		} 
		catch (IOException e) {e.printStackTrace();}
	}
	
	public void run(){				//接收该客户发来的消息
		try {
			dis=new DataInputStream(client.getInputStream());
			dos=new DataOutputStream(client.getOutputStream());
			while (true){
				int l=dis.readInt();
				byte[] data=new byte[l];
				dis.read(data);
				String msg=new String(data);
				ta.append(msg+"\r\n");
			}
		} 
		catch (IOException e) {e.printStackTrace();}
	}
}

服务器端ClientList类代码

import java.util.ArrayList;

public class ClientList {
	public static ArrayList<NetConn> list=new ArrayList();
	
	public static void send(String s){
		for (int i=list.size()-1;i>=0;i--){
			NetConn nc=list.get(i);
			nc.send(s);
		}
	}
}

客户端Client类(主类)代码

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class Client {
	
	private void work(){			//客户端界面初始化
		JFrame jf=new JFrame("聊天室-客户端");
		jf.setSize(500, 500);
		JButton btn=new JButton("发送");
		jf.add(btn);
		JTextField tf=new JTextField(20);
		JTextArea ta=new JTextArea(20,30);
		jf.add(tf);
		jf.add(ta);
		jf.setDefaultCloseOperation(3);
		jf.setLayout(new FlowLayout());
		jf.setVisible(true);
		NetConn nc=new NetConn(ta);		//建立该客户对应的NetConn对象
		if (!nc.connect()) return;		//将连接服务器部分写在NetConn类里便于判断要不要继续执行下面的代码
		nc.start();
		btn.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				String msg=tf.getText();
				nc.send(msg);
				tf.setText("");
			}
		});
	}
	
	public static void main(String[] args){
		Client c=new Client();
		c.work();
	}
}

客户端NetConn类代码

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

import javax.swing.JTextArea;

public class NetConn extends Thread{
	private Socket s;
	private JTextArea ta;
	private DataInputStream dis;
	private DataOutputStream dos;
	
	NetConn(JTextArea t){
		ta=t;
	}
	
	public void send(String msg){		//向服务器发送消息
		byte[] data=msg.getBytes();
		int l=data.length;
		try {
			dos.writeInt(l);
			dos.write(data);
		} 
		catch (IOException e) {e.printStackTrace();}
	}
	
	public void run(){			//接收服务器发来的消息
		try {
			while (true){
				int l=dis.readInt();
				byte[] data=new byte[l];
				dis.read(data);
				String msg=new String(data);
				ta.append(msg+"\r\n");
			}
		} 
		catch (IOException e) {e.printStackTrace();}
	}
	
	public boolean connect(){
		try {
			s=new Socket("192.168.0.102",9999);
			dis=new DataInputStream(s.getInputStream());
			dos=new DataOutputStream(s.getOutputStream());
			return true;
		} 
		catch (UnknownHostException e) {e.printStackTrace();} 
		catch (IOException e) {e.printStackTrace();}
		return false;
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值