Python side code:
import socket from threading import Thread import time importsys #Create storage object class Node: def __init__(self): self.Name = None # Username self.Thr = None # Socket connection object class TcpServer: user_name = {} # Store user information; dict username: Node object def __init__(self, port): """ Initialize server object port: server port """ self.server_port = port # Server port self.tcp_socket = socket.socket() # tcp socket self.tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #Port reuse self.tcp_socket.bind(self.server_port) def start(self): """ Start the server """ self.tcp_socket.listen(10) #Set the number of connections accepted by the server print( "System: Waiting for connection") while True: try: conn, addr = self.tcp_socket.accept() # Listen to the client's address and sent messages except KeyboardInterrupt: # Pressing ctrl + c will trigger this exception self.tcp_socket.close() # Close the socket sys.exit("\\ " + "System: Server exits safely!") # The program exits directly without catching exceptions except Exception as e: print(e) continue # Create a thread for the current link t = Thread(target=self.do_request, args=(conn, )) t.start() def do_request(self, conn): """ Listen for messages delivered by the client and send the message to all users """ conn_node = Node() while True: recv_data = conn.recv(1024).decode('utf-8').strip() # Get the data sent by the client info_list = recv_data.split(":") if info_list[0] == 'userName': # New User Registration data_info = info_list[-1] + 'Joined the chat' self.send_to_all(data_info) conn.send('OK'.encode('utf-8')) conn_node.Name = info_list[-1] conn_node.Thr = conn self.user_name[info_list[-1]] = conn_node if info_list[0] == 'Mass': # Play chess pieces self.send_to_other(conn_node.Name,recv_data) def send_to_all(self, msg): """ Send message to all users """ print("send_to_all:", msg) for i in self.user_name.values(): i.Thr.send(msg.encode('utf-8')) def send_to_other(self, name, msg): """ Send a message to a user other than the one currently sending the message """ print("send_to_other:", msg) for n in self.user_name: if n != name: self.user_name[n].Thr.send(msg.encode('utf-8')) else: continue if __name__ == '__main__': HOST = "192.168.10.220" POST = 7777 server = TcpServer((HOST, POST)) server.start()
Java side code:
package server; import java.io.IOException; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Map; import java.util.Scanner; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ChessServer { \t public static void main(String[] args) { ChessServer chessServer = new ChessServer(); chessServer.init(); } //Initialize the server private void init() { try { //Create ServerSocket object and listen to port 9999 @SuppressWarnings("resource") ServerSocket serversocket = new ServerSocket(7777); System.out.println("----------Server Start----------"); System.out.println("Start monitoring:"); //Create a loop so that the main thread continues to listen while (true){ \t //Make a block and listen to the client Socket socket = serversocket.accept(); System.out.println("Current socket:" + socket); //Create a new thread and pass in the client socket ServerThread server = new ServerThread(socket); //Start thread server.start(); } } catch (IOException e) { throw new RuntimeException(e); } } class ServerThread extends Thread{ //Create a Map collection private Map<String,Socket> map = new ConcurrentHashMap<>(); //Create Socket object public Socket socket; public ServerThread(Socket socket){ this.socket = socket; } //Rewrite the run method public void run(){ try { //Get the client's input stream @SuppressWarnings("resource") Scanner scanner=new Scanner(socket.getInputStream()); String msg=null; //Write a loop to continue processing the obtained information while (true) { //Determine whether the string is received if(scanner.hasNextLine()){ //getting information msg=scanner.nextLine(); //Process the string input by the client Pattern pattern=Pattern.compile("\r"); Matcher matcher=pattern.matcher(msg); msg=matcher.replaceAll(""); if(msg.startsWith("userName:")) { //Split the string from: and store the second half in userName String userName=msg.split(":")[1]; //Register the user userEnroll(userName,socket); continue; } if(msg.startsWith("Mass:")) { //Convert Map collection to Set collection Set<Map.Entry<String,Socket>> set=map.entrySet(); //Traverse the collection and send messages to all users for(Map.Entry<String,Socket> entry:set) { //Get the client's Socket object Socket client=entry.getValue(); //Do not update itself if(client != socket){ System.out.println(entry.getKey()); //Get the output stream of the client PrintStream printstream=new PrintStream(client.getOutputStream()); //Send information to client printstream.println(msg); System.out.println(msg); } } } } } } catch (IOException e) { throw new RuntimeException(e); } } //registered user private void userEnroll(String userName,Socket socket){ //Add key-value pairs to the Map collection map.put(userName,socket); //Print log System.out.println("[Username" + userName + "][Client is" + socket + "] is online!"); System.out.println("The accumulated number of people entering is:" + map.size() + "people"); } } }
c# side code:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; #nullable disable namespace UnityServer { internal class Server { static string receiveStr = ""; /// <summary> /// Server socket /// </summary> static Socket serverSocket; /// <summary> /// Dictionary of client socket and client information /// </summary> static Dictionary<Socket, ClientState> clients = new Dictionary<Socket, ClientState>(); public static void Main() { //Define socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //Bind ip and port IPAddress ip = IPAddress.Parse("192.168.10.220"); IPEndPoint iPEndPoint = new IPEndPoint(ip, 7777); serverSocket.Bind(iPEndPoint); //monitor serverSocket.Listen(0); Console.WriteLine("----------Server Start----------"); Console.WriteLine("Start listening:"); //serverSocket.BeginAccept(AcceptCallback, serverSocket); //Console.ReadLine(); List<Socket> socketList = new List<Socket>(); while(true) { socketList.Clear(); socketList.Add(serverSocket); foreach (ClientState s in clients.Values) { socketList.Add(s.socket); } //Detect readable Socket Socket.Select(socketList, null, null, 1000); foreach (Sockets in socketList) { if (s == serverSocket) { Accept(s); } else { Receive(s); } } } } /// <summary> /// Server Accept /// </summary> /// <param name="serverSocket"></param> private static void Accept(Socket serverSocket) { Console.WriteLine("Accept"); Socket clientSocket = serverSocket.Accept(); ClientState state = new ClientState(); state.socket = clientSocket; clients.Add(clientSocket, state); } /// <summary> /// Receive messages and send to all clients /// </summary> /// <param name="clientSocket"></param> private static void Receive(Socket clientSocket) { ClientState state = clients[clientSocket]; int count = clientSocket.Receive(state.readBuff); //closure if (count == 0) { clientSocket.Close(); clients.Remove(clientSocket); Console.WriteLine("A client disconnected"); return; } //Send to all clients receiveStr = Encoding.UTF8.GetString(state.readBuff, 0, count); Console.WriteLine("Receive:" + receiveStr); MassSend(receiveStr); } //Send a message public static void MassSend(string msg) { byte[] sendBytes = Encoding.UTF8.GetBytes(msg); foreach (ClientState s in clients.Values) { s.socket.Send(sendBytes); } } } }
Except for the difference in syntax, the core method is the same, which is to listen to all the socket clients that have joined and send messages to other clients except yourself. Use a collection to store newly added clients, and then distinguish whether the client that wants to receive the message includes itself. First update its own chessboard, and then tell the server to asynchronously update other clients except itself. If there is no distinction between itself and the player currently sending the message (I don’t know which user sent the message). The client’s functions need to be updated synchronously so that the server can update the board status of all players at the same time.