PhotonServer,客户端发送请求给服务端,服务端解析请求,发送回客户端响应,客户端再解析服务端发过来的响应。

本文介绍了一个使用Unity进行客户端和服务端通信的实例。客户端通过构造参数并发送请求至服务端,服务端解析请求数据并做出响应,最后客户端接收并解析服务端响应。文章详细展示了客户端和服务器端的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.(客户端发送给服务端)test中的构造参数并且发送

完整代码如下

test.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class test : MonoBehaviour {

	void Start () {
		
	}
	
	void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            SendReauest();
        }
	}

    private void SendReauest()
    {
        //构造参数
        var data = new Dictionary<byte, object>();
        //构造参数
        data.Add(1,100);
        data.Add(2,"这个是参数");
        //发送
        PhotonEngine.peer.OpCustom(1,data,true);
        //协议 前端后端
        PhotonEngine.peer.OpCustom(2,data,true);
        PhotonEngine.peer.OpCustom(3,data,true);
        PhotonEngine.peer.OpCustom(4,data,true);
        PhotonEngine.peer.OpCustom(5,data,true);
    }
}

2.服务端收到客户端的请求,并且解析数据,输出参数到log日志。

除此之外服务端还要构造一些参数并且响应给客户端。

完整代码如下:

ClientPeer.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;
using PhotonHostRuntimeInterfaces;

namespace RRGameServer
{
    class ClientPeer : Photon.SocketServer.ClientPeer
    {
        public ClientPeer(InitRequest initRequest) : base(initRequest)
        {
        }

        //当每个客户端断开时
        protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)
        {
            
        }

        //当客户端发起请求的时候
        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            switch (operationRequest.OperationCode)
            {
                case 1:
                    //解析数据
                    var data = operationRequest.Parameters;
                    object intValue;
                    data.TryGetValue(1, out intValue);
                    object StringValue;
                    data.TryGetValue(2, out StringValue);
                    //输出参数
                    MyGameServer.log.Info("收到客户端的请求,opcode:1"+intValue.ToString()+":"+StringValue.ToString());

                    //返回响应
                    OperationResponse opResponse = new OperationResponse(operationRequest.OperationCode);

                    //构造参数
                    var data2 = new Dictionary<byte, object>();
                    data2.Add(1, 100);
                    data2.Add(2, "这是服务端做的响应");
                    opResponse.SetParameters(data2);
                    //返回code,为发送过来的code,返回的参数,为发送过来的参数
                    SendOperationResponse(opResponse, sendParameters);
                    break;
                default:
                    break;
            }
        }
    }
}

3.客户端收到服务端发过来的响应,并且解析数据,输出到客户端上面。

 完整代码如下

PhotonEngine.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ExitGames.Client.Photon;
using Common;

public class PhotonEngine : MonoBehaviour,IPhotonPeerListener {
    public static PhotonEngine Instance;

   

    public static PhotonPeer peer;
    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            //当前Gameobject不会随场景的销毁而销毁
            DontDestroyOnLoad(this.gameObject);
        }
    }

    void Start () {
        peer = new PhotonPeer(this,ConnectionProtocol.Udp);
        peer.Connect("127.0.0.1:5055", "MyGame6");//通过ip连接到到对应的我们config中配置的Allpication
	}
	
	void Update () {
        peer.Service();//开启服务
	}

    private void OnDestroy()//销毁的时候
    {
        if(peer!=null&&peer.PeerState == PeerStateValue.Connected)//如果存在且保持连接状态
        {
            peer.Disconnect();//就断开连接
        }
    }

    public void DebugReturn(DebugLevel level, string message)
    {
    }

    public void OnEvent(EventData eventData)
    {
        //switch (eventData.Code)
        //{
        //    case 1:
        //        //解析数据
        //        var data = eventData.Parameters;
        //        object intValue, StringValue;
        //        data.TryGetValue(1, out intValue);              
        //        data.TryGetValue(2, out StringValue);
        //        Debug.Log("收到服务器的响应Event推送,OpCode:1" + intValue.ToString() + ":" + StringValue.ToString());
        //        break;
        //    default:
        //        break;
        //}
    }

    public void OnOperationResponse(OperationResponse operationResponse)
    {
        //DicTool.GetValue(RequestDic, (OperationCode)operationResponse.OperationCode).
        //    OnOprationRespionse(operationResponse);

        //return;
        switch (operationResponse.OperationCode)
        {
            case 1:
                Debug.Log("收到服务器的响应,OpCode:1");

                //解析数据
                var data = operationResponse.Parameters;
                object intValue;
                data.TryGetValue(1, out intValue);
                object StringValue;
                data.TryGetValue(2, out StringValue);
                Debug.Log("收到客户端的请求,OpCode:1" + intValue.ToString() + ":" + StringValue.ToString());
                break;
                    default:
                        break;
                }
        }

    public void OnStatusChanged(StatusCode statusCode)
    {
        Debug.LogError(statusCode);
    }

    //private Dictionary<OperationCode, Request> RequestDic = new Dictionary<OperationCode, Request>();

    public void AddRequest(Request r)
    {
        //RequestDic.Add(r.OpCode, r);
    }
    public void RemoveRequest(Request r)
    {
       // RequestDic.Remove(r.OpCode);
    }
}

效果图:

客户端:

 

服务端:

 

<think>好的,我现在需要帮助用户实现一个基于C#的局域网网络搜索功能。首先,我得理解用户的需求。他们想要在局域网内搜索其他设备或服务,可能类似于网络发现或者设备扫描。根据用户提供的引用内容,他们提到了使用Socket编程和PhotonServer的相关资料,所以我应该结合这些信息来构建解决方案。 首先,我得忆一下Socket编程的基本步骤。根据引用[1],Socket编程通常包括创建实例、绑定IP和端口、监听连接、接受连接、数据传输和断开连接。不过,用户的需求是搜索局域网内的设备,这可能更多涉及广播或组播的方式,而不是传统的客户端-服务器模型。 接下来,我需要确定使用哪种协议。UDP广播是一种常见的方法,因为它在局域网内发送消息不需要提前建立连接,适合发现服务。引用中没有直接提到UDP广播,但结合Socket的知识,我知道C#的UdpClient类可以用于实现这一点。 然后,考虑如何设计搜索功能。服务端需要监听特定的端口,等待搜索请求,而客户端发送广播消息到该端口。服务端收到请求后,复自己的信息,如IP地址或设备名称。这样,客户端就能收集到所有响应的设备信息。 接下来,我需要检查用户提供的引用是否有相关示例。引用[1]提到的是基本的Socket步骤,而引用[2]关于PhotonServer可能不太相关,但用户可能希望使用已有的库或框架。不过,如果用户希望原生实现,使用C#自带的Socket或UdpClient可能更合适。 然后,我需要考虑代码结构。服务端应该在一个循环中持续监听,客户端发送广播后等待复。此外,处理超时和异步操作也是必要的,以避免程序阻塞。 可能的问题包括端口选择、广播地址的正确使用以及如何处理多网卡的情况。例如,广播地址通常是255.255.255.255,但有时可能需要针对特定子网。另外,确保防火墙设置允许UDP通信,否则消息可能被阻止。 最后,我需要编写示例代码,展示如何实现客户端服务端的基本功能,并解释关键步骤,如绑定端点、发送广播、接收响应等。同时,要提醒用户注意可能的异常处理和性能优化,比如设置超时时间,使用异步方法提高响应速度等。 总结步骤: 1. 服务端监听UDP端口,等待搜索请求。 2. 客户端发送UDP广播到特定端口。 3. 服务端收到请求发送响应。 4. 客户端收集响应,显示可用设备。 现在需要将这些步骤转化为具体的代码示例,并确保符合C#的Socket编程规范,同时参考用户提供的引用内容中的结构,比如使用正确的命名空间和类。</think>以下是如何用C#实现局域网网络搜索功能的实现方案: ### 一、技术实现原理 基于UDP广播实现设备发现,通过$Socket$类实现局域网通信。核心流程包含: 1. 服务端持续监听UDP端口 2. 客户端发送广播探测包 3. 服务端响应设备信息 4. 客户端收集响应设备[^1] ### 二、完整实现代码 ```csharp // 服务端代码(被搜索设备) using System.Net; using System.Net.Sockets; using System.Text; class NetworkScannerServer { private const int PORT = 8888; public static void Start() { UdpClient listener = new UdpClient(); listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); listener.Client.Bind(new IPEndPoint(IPAddress.Any, PORT)); try { while (true) { IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); byte[] data = listener.Receive(ref remoteEP); string message = Encoding.ASCII.GetString(data); if (message == "DISCOVERY_REQUEST") { string response = Dns.GetHostName() + "|" + GetLocalIP(); byte[] respData = Encoding.ASCII.GetBytes(response); listener.Send(respData, respData.Length, remoteEP); } } } finally { listener.Close(); } } private static string GetLocalIP() { return Dns.GetHostEntry(Dns.GetHostName()) .AddressList.First(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString(); } } // 客户端代码(搜索设备) class NetworkScannerClient { private const int PORT = 8888; private const int TIMEOUT = 2000; public static Dictionary<string, string> SearchDevices() { var devices = new Dictionary<string, string>(); UdpClient client = new UdpClient() { EnableBroadcast = true }; byte[] requestData = Encoding.ASCII.GetBytes("DISCOVERY_REQUEST"); client.Send(requestData, requestData.Length, new IPEndPoint(IPAddress.Broadcast, PORT)); DateTime startTime = DateTime.Now; while ((DateTime.Now - startTime).TotalMilliseconds < TIMEOUT) { if (client.Available > 0) { IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); byte[] data = client.Receive(ref remoteEP); string[] parts = Encoding.ASCII.GetString(data).Split('|'); devices[parts[0]] = parts[1]; } Thread.Sleep(100); } return devices; } } ``` ### 三、关键代码解析 1. `IPAddress.Broadcast`:使用255.255.255.255作为广播地址 2. `SocketOptionName.ReuseAddress`:允许多个套接字绑定到相同端口 3. `EnableBroadcast = true`:启用UDP广播功能 4. 设备响应格式:主机名|IP地址 的ASCII编码格式 ### 四、部署注意事项 1. 需确保防火墙允许UDP 8888端口通信 2. 建议使用异步编程优化响应速度 3. 可扩展为携带更多设备信息(如服务类型、版本号等)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值