局域网内实现 服务器自动广播Ip 客户端自动获取连接
1需求 分析
1 教师端需要使用UDP 协议广播给局域网所有客户端,每隔固定时间广播一次
2 学生端需要监听固定端口Ip,收到后保留下来,同时保存标识,在IP没有发生变化时,不需弹出Ip弹窗
2制作
教师端服务器 代码
使用控制台做服务器,自己拷贝到服务器简单修改下
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
using UnityEngine.Networking;
public class Server : MonoSingleton<Server>
{
private static Socket sock;
public static IPEndPoint iep1;
private static byte[] data;
private Thread t;
public int udpPort = 9050;
public string ip = "";
public void Start()
{
GetIpLocal();
BroadcastIP();
}
public void BroadcastIP()
{
sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
iep1 = new IPEndPoint(IPAddress.Broadcast, udpPort);
data = Encoding.ASCII.GetBytes("111");
sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
t = new Thread(BroadcastMessage);
t.Start();
}
private void BroadcastMessage()
{
while (true)
{
sock.SendTo(data, iep1);
Thread.Sleep(2000); ///每2000 毫秒广播一次数据
Debug.Log("每2000 毫秒广播一次数据");
}
}
/// <summary>
/// c# 本机Ip
/// </summary>
/// <returns></returns>
private string GetIP()
{
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adater in adapters)
{
if (adater.Supports(NetworkInterfaceComponent.IPv4))
{
UnicastIPAddressInformationCollection UniCast = adater.GetIPProperties().UnicastAddresses;
if (UniCast.Count > 0)
{
foreach (UnicastIPAddressInformation uni in UniCast)
{
if (uni.Address.AddressFamily == AddressFamily.InterNetwork)
{
//m_ip = uni.Address.ToString();
return uni.Address.ToString();
}
}
}
}
}
return null;
}
/// <summary>
/// unity 本地Ip
/// </summary>
/// <returns></returns>
public string GetIpLocal()
{
#if UNITY_5
ip = Network.player.ipAddress;
return ip;
#else
ip = GetIP(ADDRESSFAM.IPv4);
return ip ;
#endif
}
public static string GetIP(ADDRESSFAM Addfam)
{
//Return null if ADDRESSFAM is Ipv6 but Os does not support it
if (Addfam == ADDRESSFAM.IPv6 && !Socket.OSSupportsIPv6)
{
return null;
}
string output = "";
foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
{
#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
NetworkInterfaceType _type1 = NetworkInterfaceType.Wireless80211;
NetworkInterfaceType _type2 = NetworkInterfaceType.Ethernet;
if ((item.NetworkInterfaceType == _type1 || item.NetworkInterfaceType == _type2) && item.OperationalStatus == OperationalStatus.Up)
#endif
{
foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
{
//IPv4
if (Addfam == ADDRESSFAM.IPv4)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
{
output = ip.Address.ToString();
Debug.Log("啊" + output);
}
}
//IPv6
else if (Addfam == ADDRESSFAM.IPv6)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetworkV6)
{
output = ip.Address.ToString();
}
}
}
}
}
return output;
}
}
public enum ADDRESSFAM
{
IPv4, IPv6
}
学生端代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System;
using UnityEngine.UI;
public class ClitetGetServerIp : MonoBehaviour
{
public static ClitetGetServerIp Instance;
byte[] data;
string Error_Message;
private Thread t;
public int udpPort = 9050;
public string ip;
public string Ip
{
get
{
return ip;
}
private set { }
}
public bool isGetServerIp;
public GameObject canvas;
public Button button;
public Text iptxt;
public bool isCheck;
void Awake()
{
Instance = this;
GetSeverIP();
//PlayerPrefs.DeleteAll();
button.onClick.AddListener(() => {
PlayerPrefs.SetString("Ip", ip);
GameInit.Init();
canvas.SetActive(false);
});
}
private void Update()
{
if (isGetServerIp)
{
if (!isCheck)
{
if (PlayerPrefs.HasKey("Ip"))
{
Debug.Log("Ip");
string oldIp = PlayerPrefs.GetString("Ip");
if (string.Equals(ip, oldIp))
{
canvas.gameObject.SetActive(false);
GameInit.Init();
}
else
{
canvas.gameObject.SetActive(true);
}
}
else
{
Debug.Log("显示");
canvas.gameObject.SetActive(true);
}
iptxt.text = ip;
isCheck = true;
}
}
}
void GetSeverIP()
{
if (isGetServerIp) return;
try
{
t = new Thread(Receive);
t.Start();
}
catch (Exception e)
{
Debug.LogError("错误信息:" + e.Message);
}
}
Socket sock;
void Receive()
{
sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, udpPort);
sock.Bind(iep);
EndPoint ep = (EndPoint)iep;
byte[] data = new byte[1024];
int recv = sock.ReceiveFrom(data, ref ep);
string stringData = Encoding.ASCII.GetString(data, 0, recv);
Debug.Log(String.Format("received: {0} from: {1}", stringData, ep.ToString()));
string[] condition = { ":" };
ip = ep.ToString().Split(condition, StringSplitOptions.None)[0];
isGetServerIp = true;
sock.Close();
}
}
3 百度网盘工程文件:
链接:https://pan.baidu.com/s/149ErALcszXynS9BoCNi0VQ
提取码:osyk
复制这段内容后打开百度网盘手机App,操作更方便哦
版本: unity 5.6.6
4 服务器其他socket 连接时,调用获取本地IP时注意
Server.GetIP(ADDRESSFAM.IPv4)) 在断网时不会返回数值,需要设置为127.0.0.1 。否则断网时无法在一台电脑同时跑服务器和客户端
如下代码示例 中 :string.IsNullOrEmpty(Server.GetIP(ADDRESSFAM.IPv4)) 进行判断
public static int m_Point = 10110;
public static Socket m_ServerSocket;
public void Init()
{
Main();
InitDBModle();
}
static void Main()
{
// Debug.Log(Server.Instance.GetIpLocal());
// Debug.Log(Server.GetIP(ADDRESSFAM.IPv4));
m_ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
if (string.IsNullOrEmpty(Server.GetIP(ADDRESSFAM.IPv4)))
{
m_ServerSocket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), m_Point));
}
else
{
m_ServerSocket.Bind(new IPEndPoint(IPAddress.Parse(Server.GetIP(ADDRESSFAM.IPv4)), m_Point));
}
m_ServerSocket.Listen(3000);
Debug.Log("启动监听成功");
Thread mthread = new Thread(ListenClientCallBack);
mthread.Start();
}
public static void ListenClientCallBack()
{
// Debug.Log("00000000000000000000");
while (true)
{
Socket socket = m_ServerSocket.Accept();
Debug.LogFormat("客户端{0}已经连接", socket.RemoteEndPoint.ToString());
Role role = new Role();
role.LoginTime = System.DateTime.Now;
Debug.Log(role.LoginTime);
ClientSocket clientSocket = new ClientSocket(socket, role);
//role.clientSocket = clientSocket;
RoleMgr.Instance.GetRoles.Add(role);
}
}