上两篇文章《网络编程——1对1,单次通信》,以及《网络通信——1对1,多次通信》讲解了一些比较简单的通信,今天要讲一对多,一个服务器与多个客户端进行通话。原理如下图,通过多线程实现。
下面给出一对多,一个服务器多个客户端的收发消息关系图。下图表示,创建了三个与客户端对话的Communication层,每个客户端分别与各自对应的线程通话,从而实现一对多通信。
同样,与之前两篇一样,先给出一个接口,存储端口信息。
package gw.network.common;
public interface INetConfig {
int DEFAULT_PORT = 54188;
}
1.观察者模式
为了能够时刻监听到客户端连接,决定使用观察者模式,给出两个接口
消息接收者:
package gw.network.common;
//接收信息
public interface IListener {
void processMessage(String message);
}
消息发出者:
package gw.network.common;
//消息发出者
public interface ISpeaker {
void addListener(IListener listener); // 订阅,增加听众
void removeListener(IListener listener); // 退订,删除听众
}
2.服务器
如果之前认真看了前两篇文章的同学,本类只需详细的看一下run()
方法,和实现的接口中的方法。
package gw.network.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import gw.network.common.ISpeaker;
import gw.network.common.IListener;
import gw.network.common.Communication;
import gw.network.common.INetConfig;
//三架马车:dis,dos,socket
//MulServer消息发送者
public class MulServer implements Runnable, ISpeaker{
private int port;
private ServerSocket server;
private boolean goon;
private List<IListener> listenerList;
public MulServer() {
this.listenerList = new ArrayList<>();
this.port = INetConfig.DEFAULT_PORT;
}
public void startup() throws IOException {
if(goon == true) {
speakOut("服务器已启动!");
return;
}
speakOut("启动服务器,请稍后……");
server = new ServerSocket(port);
speakOut("服务器启动成功!");
goon = true;
new Thread(this).start(