服务器之家

服务器之家 > 正文

C#中Socket与Unity相结合示例代码

时间:2022-01-24 13:44     来源/作者:青鱼谷雨

前言

初步接触了Socket,现使其与Unity相结合,做成一个简单的客户端之间可以互相发送消息的一个Test。下面话不多说了,来一起看看详细的介绍吧。

方法如下:

首先,是服务端的代码。

创建一个连接池,用于存储客户端的数量。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Collections.Generic;
 
 
namespace Server
{
 /// <summary>
 /// 对象池
 /// </summary>
 public class Conn
 {
  //常量,用于表示传输的字节最大数量,最大接收的字节数
  public const int buffer_Size = 1024;
 
  //Socket
  public Socket socket;
 
  //是否连接
  public bool isUse = false;
 
  //传输数组,用来存储接受到的数据
  public byte[] readBuff = new byte[buffer_Size];
 
 
  public int buffCount = 0;
 
  /// <summary>
  /// 构造函数
  /// </summary>
  public Conn()
  {
   readBuff = new byte[buffer_Size];
  }
 
  /// <summary>
  /// 初始化
  /// </summary>
  /// <param name="socket"></param>
  public void Init(Socket socket)
  {
   this.socket = socket;
   isUse = true;
   buffCount = 0;
  }
 
  /// <summary>
  /// 缓冲区剩下的字节数
  /// </summary>
  /// <returns></returns>
  public int BuffRemain()
  {
   return buffer_Size - buffCount;
  }
 
  /// <summary>
  /// 获得客户端地址
  /// </summary>
  /// <returns></returns>
  public string GetAdress()
  {
   if (!isUse)
   {
    return "无法获得地址";
   }
   else
   {
    return socket.RemoteEndPoint.ToString();
   }
 
  }
 
  /// <summary>
  /// 关闭连接
  /// </summary>
  public void Close()
  {
   if (!isUse)
   {
    return;
 
   }
   else
   {
    Console.WriteLine("断开连接" + GetAdress());
    socket.Close();
    isUse = false;
   }
  }
 }
}

对象池创建完成后,需要在创建一个连接类,用来维护客户端的连接。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
 
 
namespace Server
{
 class Serv
 {
  //监听套接字
  public Socket listenfd;
 
  //客户端链接
  public Conn[] conns;
 
  //最大的连接数量
  public int maxConn = 50;
 
  //获取链接池索引,返回负数表示获取失败
  public int NewIndex()
  {
   if(conns==null)
   {
    return -1;
   }
   for (int i = 0; i < conns.Length;i++ )
   {
    if(conns[i]==null)
    {
     conns[i] = new Conn();
     return i;
    }else if(conns[i].isUse==false)
    {
     return i;
    }
   }
   return -1;
  }
 
  //开启一个服务器
  public void Start(string host,int port)
  {
   conns = new Conn[maxConn];
 
 
   for (int i = 0; i < maxConn;i++ )
   {
    conns[i] = new Conn();
   }
 
 
   listenfd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 
   IPAddress ipAdr = IPAddress.Parse(host);
   IPEndPoint ipEp = new IPEndPoint(ipAdr, port);
 
   //与一个本地终结点相关联
   listenfd.Bind(ipEp);
 
   //监听
   listenfd.Listen(maxConn);
 
   listenfd.BeginAccept(AcceptCb, listenfd);
 
  }
 
  //AcceptCb回调
  public void AcceptCb(IAsyncResult ar)
  {
   try
   {
    Socket sSocket = ar.AsyncState as Socket;
    Socket socket = sSocket.EndAccept(ar);
 
    int index = NewIndex();
    if(index<0)
    {
     socket.Close();
     Console.WriteLine("连接已满");
    }
    else
    {
     Conn conn = conns[index];
     conn.Init(socket);
     string adr = conn.GetAdress();
     Console.WriteLine("客户端连接[" + adr + "Conn池ID: " + index);
 
     conn.socket.BeginReceive(conn.readBuff, conn.buffCount, conn.BuffRemain(), SocketFlags.None, ReceiveCb, conn);
 
    }
 
    listenfd.BeginAccept(AcceptCb, listenfd);
 
 
   }catch(SocketException ex)
   {
    Console.WriteLine(ex);
   }
 
  }
 
  //ReceiveCb回调
  public void ReceiveCb(IAsyncResult ar)
  {
   Conn conn = (Conn)ar.AsyncState;
   try
   {
    int count = conn.socket.EndReceive(ar);
    if(count<=0)
    {
     Console.WriteLine("收到:" + conn.GetAdress() + "断开连接");
     conn.Close();
     return;
    }
    string str = Encoding.UTF8.GetString(conn.readBuff,0,count);
    Console.WriteLine("接收到[" + conn.GetAdress() + "]数据" + str);
 
    byte[] bytes = Encoding.UTF8.GetBytes(str);
 
    for (int i = 0; i < conns.Length;i++ )
    {
     if(conns[i]==null)
      continue;
 
     if (!conns[i].isUse)
      continue;
     Console.WriteLine("将消息传送给" + conns[i].GetAdress());
     conns[i].socket.Send(bytes);
    }
    conn.socket.BeginReceive(conn.readBuff, conn.buffCount, conn.BuffRemain(), SocketFlags.None,ReceiveCb, conn);
 
   }
   catch(SocketException ex)
   {
    Console.WriteLine(ex);
    Console.WriteLine("收到:" + conn.GetAdress() + "断开连接");
    conn.Close();
   }
 
  }
 }
}

最后是创建一个Unity的工程,搭建一个简单的页面,通过下面的代码你可以了解需要哪些组件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using UnityEngine.UI;
using System.Collections.Generic;
using System;
 
public class net : MonoBehaviour
{
 //ip和端口
 public InputField hostInput;
 public InputField portInput;
 
 //显示客户端接受的消息
 public Text recvText;
 public string recvStr;
 
 //显示客户端IP和端口
 public Text clientText;
 
 //聊天输入框
 public InputField TextInput;
 
 Socket socket;
 
 const int buffer_Size = 1024;
 public byte[] readBuff = new byte[buffer_Size];
 
 
 void FixedUpdate()
 {
  recvText.text = recvStr;
 }
 
 
 //连接服务器(需要一个Button触发)
 public void Connetion()
 {
  recvText.text = "";
 
  socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 
  string host = hostInput.text;
  int port = int.Parse(portInput.text);
 
  socket.Connect(host, port);
  clientText.text = "客户端地址:"+socket.LocalEndPoint.ToString();
  socket.BeginReceive(readBuff, 0, buffer_Size, SocketFlags.None, ReceiveCb,socket);
 
 }
 
 /// <summary>
 /// 接受数据
 /// </summary>
 /// <param name="ar"></param>
 public void ReceiveCb(IAsyncResult ar)
 {
  
  try
  {
   int count = socket.EndReceive(ar);
 
   string str = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
 
   if (recvStr.Length > 300) recvStr = "";
 
   recvStr += socket.LocalEndPoint.ToString()+str + "\n";
   Debug.Log("12346");
   socket.BeginReceive(readBuff, 0, buffer_Size, SocketFlags.None, ReceiveCb, socket);
  }catch(SocketException ex)
  {
   Debug.Log(ex);
  }
 }
 
 /// <summary>
 /// 发送数据,(需要一个Button触发)
 /// </summary>
 public void Send()
 {
  string str = TextInput.text;
  byte[] tex = System.Text.Encoding.UTF8.GetBytes(str);
  try
  {
   socket.Send(tex);
  
  }
  catch(SocketException ex)
  {
   Debug.Log(ex);
  }
 }
}

以上内容出自罗培羽老师《unity3d网络游戏实战》一书。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。

标签:

相关文章

热门资讯

蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
2021年耽改剧名单 2021要播出的59部耽改剧列表
2021年耽改剧名单 2021要播出的59部耽改剧列表 2021-03-05
返回顶部