赞
踩
python端代码:
import socket from threading import Thread import time import sys # 创建存储对象 class Node: def __init__(self): self.Name = None # 用户名 self.Thr = None # 套接字连接对象 class TcpServer: user_name = {} # 存储用户信息; dict 用户名:Node对象 def __init__(self, port): """ 初始化服务器对象 port: 服务器端口 """ self.server_port = port # 服务器端口 self.tcp_socket = socket.socket() # tcp套接字 self.tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 端口重用 self.tcp_socket.bind(self.server_port) def start(self): """ 启动服务器 """ self.tcp_socket.listen(10) # 设置服务器接受的链接数量 print( "系统:等待连接") while True: try: conn, addr = self.tcp_socket.accept() # 监听客户端的地址和发送的消息 except KeyboardInterrupt: # 按下ctrl+c会触发此异常 self.tcp_socket.close() # 关闭套接字 sys.exit("\n" + "系统:服务器安全退出!") # 程序直接退出,不捕捉异常 except Exception as e: print(e) continue # 为当前链接创建线程 t = Thread(target=self.do_request, args=(conn, )) t.start() def do_request(self, conn): """ 监听客户端传送的消息,并将该消息发送给所有用户 """ conn_node = Node() while True: recv_data = conn.recv(1024).decode('utf-8').strip() # 获取客户端发来的数据 info_list = recv_data.split(":") if info_list[0] == 'userName': # 新用户注册 data_info = info_list[-1] + '加入了聊天' 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': # 下棋子 self.send_to_other(conn_node.Name,recv_data) def send_to_all(self, msg): """ 对所有用户发送消息 """ 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): """ 对除了当前发送信息的用户外的其他用户发送消息 """ 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端代码:
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 { public static void main(String[] args) { ChessServer chessServer = new ChessServer(); chessServer.init(); } //初始化服务器 private void init() { try { //创建ServerSocket对象,监听9999端口 @SuppressWarnings("resource") ServerSocket serversocket = new ServerSocket(7777); System.out.println("----------服务器启动----------"); System.out.println("开始监听:"); //创建一个循环,使主线程持续监听 while (true){ //做一个阻塞,监听客户端 Socket socket = serversocket.accept(); System.out.println("当前socket:" + socket); //创建一个新的线程,将客户端socket传入 ServerThread server = new ServerThread(socket); //启动线程 server.start(); } } catch (IOException e) { throw new RuntimeException(e); } } class ServerThread extends Thread{ //创建一个Map集合 private Map<String,Socket> map = new ConcurrentHashMap<>(); //创建Socket对象 public Socket socket; public ServerThread(Socket socket){ this.socket = socket; } //重写run方法 public void run(){ try { //获取客户端的输入流 @SuppressWarnings("resource") Scanner scanner=new Scanner(socket.getInputStream()); String msg=null; //写一个循环来持续处理获取到的信息 while (true) { //判断是否接收到了字符串 if(scanner.hasNextLine()){ //获取信息 msg=scanner.nextLine(); //处理客户端输入的字符串 Pattern pattern=Pattern.compile("\r"); Matcher matcher=pattern.matcher(msg); msg=matcher.replaceAll(""); if(msg.startsWith("userName:")) { //将字符串从:拆分开,后半部分存入userName中 String userName=msg.split(":")[1]; //注册该用户 userEnroll(userName,socket); continue; } if(msg.startsWith("Mass:")) { //将Map集合转换为Set集合 Set<Map.Entry<String,Socket>> set=map.entrySet(); //遍历集合,向所有用户发送消息 for(Map.Entry<String,Socket> entry:set) { //取得客户端的Socket对象 Socket client=entry.getValue(); //不更新自己 if(client != socket){ System.out.println(entry.getKey()); //取得client客户端的输出流 PrintStream printstream=new PrintStream(client.getOutputStream()); //向客户端发送信息 printstream.println(msg); System.out.println(msg); } } } } } } catch (IOException e) { throw new RuntimeException(e); } } //注册用户 private void userEnroll(String userName,Socket socket){ //将键值对添加入Map集合中 map.put(userName,socket); //打印日志 System.out.println("[用户名为"+userName+"][客户端为"+socket+"]上线了!"); System.out.println("积累进入人数为:"+map.size()+"人"); } } }
c#端代码:
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> /// 服务端socke /// </summary> static Socket serverSocket; /// <summary> /// 客户端socket以及客户端信息的字典 /// </summary> static Dictionary<Socket, ClientState> clients = new Dictionary<Socket, ClientState>(); public static void Main() { //定义socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //绑定ip和端口 IPAddress ip = IPAddress.Parse("192.168.10.220"); IPEndPoint iPEndPoint = new IPEndPoint(ip, 7777); serverSocket.Bind(iPEndPoint); //监听 serverSocket.Listen(0); Console.WriteLine("----------服务器启动----------"); Console.WriteLine("开始监听:"); //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); } //检测可读Socket Socket.Select(socketList, null, null, 1000); foreach (Socket s in socketList) { if (s == serverSocket) { Accept(s); } else { Receive(s); } } } } /// <summary> /// 服务端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> /// 接收消息以及发送给所有客户端 /// </summary> /// <param name="clientSocket"></param> private static void Receive(Socket clientSocket) { ClientState state = clients[clientSocket]; int count = clientSocket.Receive(state.readBuff); //关闭 if (count == 0) { clientSocket.Close(); clients.Remove(clientSocket); Console.WriteLine("有一个客户端断开连接"); return; } //发送给所有客户端 receiveStr = Encoding.UTF8.GetString(state.readBuff, 0, count); Console.WriteLine("Receive:" + receiveStr); MassSend(receiveStr); } //发送消息 public static void MassSend(string msg) { byte[] sendBytes = Encoding.UTF8.GetBytes(msg); foreach (ClientState s in clients.Values) { s.socket.Send(sendBytes); } } } }
除了语法有区别,核心方法是一样的,监听所有加入的socket端客户,发送消息给除自己外的其它客户端。用一个集合存放新加入的客户端,然后区分要收消息的客户端是否包含自己,先更新自身棋盘,再告诉服务器异步更新除自己外的其他客户端,如果没有区分自己和当前发送消息的玩家(不知道是哪个用户发送的消息),客户端的功能需要同步更新让服务器同时更新所有玩家棋盘状态。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。