基于socket的多客户端之间互相通信
- 服务端循环监听客户端,为每一个连接的客户端创建一个子线程,并将线程添加到一个集合列表中;
- 子线程中将消息以json的格式进行封装并添加到一个集合列表中;
- 创建一个线程用于消息的解析与转发;
- 客户端新建Socket并指定服务端ip和端口号进行连接;
- 客户端发送的消息开头加上消息到达方的id,用斜杠或其他特殊符号区分开;
public class ServerHost {
// 消息列表
static List mMsgList = new ArrayList();
// 线程列表
static List mThreadList = new ArrayList();
public static void main(String[] args) throws IOException {
int mSocketId = 0;
ServerSocket serverSocket = new ServerSocket(12345);
Socket socket = null;
//创建一个线程用于解析并转发消息
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
if (mMsgList.size() > 0) {
// 获取列表中第一个json消息
JSONObject msgJson2 = (JSONObject)mMsgList.get(0);
for (int i = 0; i < mThreadList.size(); i++) {
ServerThread serverThread = (ServerThread)mThreadList.get(i);
if (serverThread.mSocketId == msgJson2.getInt("to")) {
try {
DataOutputStream dos = new DataOutputStream(serverThread.socket.getOutputStream());
dos.writeUTF(msgJson2.get("msg").toString());
dos.flush();
break;
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 移除第一个json消息
mMsgList.remove(0);
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//服务端在while里不断监听是否有新的客户端接入,如果有则为该新的客户端创建一个新的线程,在里面封装消息
while(true) {
try {
socket = serverSocket.accept();
// 封装消息线程
ServerThread serverThread = new ServerThread(socket, mSocketId, mMsgList);
serverThread.start();
// 将为每一个客户端新建的子线程添加到集合中
mThreadList.add(serverThread);
// mSocketId当作该客户端的id
mSocketId++;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
为每一个连接的客户端新建的子线程,进行消息的封装:
class ServerThread extends Thread {
Socket socket = null;
int mSocketId = 0;
static List mMsgList = null;
DataInputStream dis = null;
DataOutputStream dos = null;
public ServerThread(Socket socket, int mSocketId, List mMsgList) {
super();
this.socket = socket;
this.mSocketId = mSocketId;
this.mMsgList = mMsgList;
}
public void run() {
try {
//获取socket的输入输出流
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
while (true) {
String msgRecv = dis.readUTF();
//json封装消息
JSONObject msgJson = new JSONObject();
msgJson.put("from", mSocketId);
msgJson.put("to", Integer.parseInt(msgRecv.split("/")[0]));
msgJson.put("msg", msgRecv.split("/")[1]);
// 将json消息添加到集合中
mMsgList.add(msgJson);
}
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
}
实现过程
在服务器中为每一个连接到服务器的客户端开启一个子线程,并在这个子线程中循环监听这个客户端是否发过来消息,在上面可以看到服务端接收到消息后,将这条消息封装到了msgJson中并添加到了集合mMsgList中。到这里服务器就可以收到客户端发过来的消息了,服务器收到消息后要做的工作就是将这条消息发送给客户端,(从实现原理图中可以看出服务器起到一个中转的作用)
那么怎样实现这个功能呢?它的实现也不难,从上面的描述我们可以知道只要客户端向服务器发送一条消息,我们就会将这条消息放到一个集合mMsgList中,也就是说只要服务器收到消息mMsgList这个集合就不为空,只要mMsgList这个集合不为空就说明服务器还拥有未转发的消息,需要转发。
怎么实现转发呢? 首先这里有两个集合一个是json消息的集合mMsgList ,另一个是为每一个客户端Socket开启的一个子线程SocketThread的集合mThreadList。这两个集合的关系是每一个msgJson肯定是mThreadList中的一个SocketThread(客户端)发送的。当SocketThread的id与msgJson中的to(即消息的到达方)相等时,因为每一个客户端(假设是clientSocket1)连接到服务器时都要开启一个SocketThread子线程,在这个子线程中有clientSocket1的引用,所以当相等时就说明这个Message是发送给这个clientSocket1的。然后通过这个clientSocket1的DataOutputStream将这个消息发送给这个客户端。
下一篇: 客户端调用
推荐阅读
-
基于socket的多客户端之间互相通信
-
Java基于socket实现的客户端和服务端通信功能完整实例
-
Java基于socket实现的客户端和服务端通信功能完整实例
-
android基于socket的局域网内服务器与客户端加密通信
-
Go语言基于Socket编写服务器端与客户端通信的实例
-
linux网络编程之用socket实现简单客户端和服务端的通信(基于TCP)
-
socket实现客户端与服务端之间的Tcp通信
-
网络编程(InetAddress类、Socket和ServerSocket、实现客户端和服务器之间的双向通信)
-
linux网络编程之用socket实现简单客户端和服务端的通信(基于UDP)
-
android基于socket的局域网内服务器与客户端加密通信