这是基于TCP通信的客户端与服务器的实现。以简单的聊天窗作为模板,实现多个客户端之间的通信
一、客户端
分析
我们的客户端分为2个模块,界面显示模块Client和通信模块Connect。
本文中,首字母大写的Client和Connect表示类,首字母小写的client和connect表示所创建的对象
发送数据:
是通过点击按钮button来发送数据,于是我们可以对button创建一个用于发送信息的监听器,当我们点击button时,调用**通信模块的发送函数connect.send(String msg)**来发送消息。可以发现,这个模块通过监听器实现起来比较轻松,因为只有点击按钮时,才会发送消息。这意味着我们只需要把发送函数写好就行。
接收数据
由于我们无法判断对方什么时候给我们发送数据,所以我们需要一个while(true)循环来接收信息。这个循环应该在connect的初始化函数的最后。
但是,由于我们要先构造Connect的对象connect,之后才能根据connect构建按钮的监听器,所以,如果我们直接在那添加循环,我们的程序就会卡在这,影响我们构建监听器,从而影响我们发送信息。为了解决这个问题,我们可以构建一个线程,在线程中进行while(true)循环,这样就不会影响我们接下来的程序运行了。
解决了这个问题,我们还面临着一个问题,就是如何把在通信模块connect接收到的消息传送个界面模块client。
模块Client 与 通信模块Connect 之间的消息传输
我们需要一个something来在这2个模块之间实现数据传输。
发送数据好说,在client里创建一个connect对象,把信息String msg当成参数传递给connect里的发送函数,形如 connect.send(msg);
接收数据就有点难度了。最简单的方法就是在Connect对象里创建一个Client对象,当在Client对象client里创建一个Connect对象connect时,把client自身传给connect。这样做也不是不想,但不够秀。
我们可以这样做:
- 我们可以通过创建interface接口RecvInterface,里面只有一个处理数据的空函数
public void handleData(String msg);
。 - 然后让Client继承RrcvInterface,改写
handleData
函数。 - 之后只在Connect里创建一个RecvInterface对象recvInterface,并将client传给connect里的recvInterface
这样当我们处理接收信息时,只需要在connect里 recvInterface.handleData(line);
即可。
客户端界面
结果:
大框显示接收到的数据
小框显示要发送的数据
(一) 构建接口RecvInterface
/*接口很简单,只有一个处理数据的函数就行*/
public interface RecvInterface {
public void handleData(String msg);
}
(二) 界面Client
就是一个简单的UI设计,在初始化完成后,将该界面this作为一个 接口 传入到通信模块
/*Client继承接口RecvInterface,方面处理接收到的消息*/
public class Client implements RecvInterface {
private Connect connect = new Connect();
private JTextArea log;
/*初始化模块*/
public void initUI() {
/*界面设计*/
JFrame jf = new JFrame();
jf.setDefaultCloseOperation(3);
jf.setLayout(new FlowLayout());
//JTextPane可以实现字体颜色和图片插入
log = new JTextArea(12, 40);
//滚动面板
JScrollPane sp = new JScrollPane(log);
jf.add(sp);
JTextField input = new JTextField(20);
jf.add(input);
JButton btn = new JButton("Send");
jf.add(btn);
jf.setSize(600, 500);
jf.setVisible(true);
/*
创建通信模块connect
初始化connect
将自己this传入connect
*/
connect.init();
connect.addRecvInterface(this);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String sendMsg = input.getText();
connect.send(sendMsg);
}