网络实现资源共享和信息传递,
ip地址识别机器,端口进行通信。
TCP(三次握手,确定连接双方的序列号(seq)和确认号(ack))必须双方建立连接。UDP不需要
数据不一定能确认接收方接收,会等待接收方回应。
套接字是支持TCP/IP协议网络通信的基本操作单元。
同步socket
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace sever
{
class Program
{
//指定套接字信息
static Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
IPEndPoint iPEnd = new IPEndPoint(ip, 8888);
socket.Bind(iPEnd);
socket.Listen(0);//backlog指定队列中最多连接数。
Console.WriteLine("服务端启动");
while (true)
{
Socket conn= socket.Accept();
byte[] b = new byte[1024];
int count = conn.Receive(b);
string msg = Encoding.Unicode.GetString(b);
Console.WriteLine("收到客户端 {0} 消息:{1}",conn.LocalEndPoint,msg);
byte[] re = Encoding.Unicode.GetBytes("响应客户:"+System.DateTime.Now.ToString());
conn.Send(re);
}
}
}
}
using UnityEngine;
using UnityEngine.UI;
using System.Net.Sockets;
using System.Text;
public class ClientWork : MonoBehaviour
{
public InputField ip, port;
public Button conn;
public Text clienInfo;
public Text msg;
public void connServer()
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(ip.text, int.Parse(port.text));
clienInfo.text = socket.LocalEndPoint.ToString();
socket.Send(Encoding.Unicode.GetBytes("hello server"));
byte[] b = new byte[1024];
socket.Receive(b);
msg.text = Encoding.Unicode.GetString(b);
}
}
异步模式下,服务端使用BeginAccept和EndAccept方法。
using System;
using System.Net;
using System.Net.Sockets;
public 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();
}
//Socket
listenfd = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
//Bind
IPAddress ipAdr = IPAddress.Parse(host);
IPEndPoint ipEp = new IPEndPoint(ipAdr, port);
listenfd.Bind(ipEp);
//Listen
listenfd.Listen(maxConn);
//Accept
listenfd.BeginAccept(AcceptCb, null);
Console.WriteLine("[服务器]启动成功");
}
//Accept回调
private void AcceptCb(IAsyncResult ar)
{
try
{
Socket socket = listenfd.EndAccept(ar);
int index = NewIndex();
if (index < 0)
{
socket.Close();
Console.Write("[警告]链接已满");
}
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, null);
}
catch (Exception e)
{
Console.WriteLine("AcceptCb失败:" + e.Message);
}
}
private 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 = System.Text.Encoding.UTF8.GetString(conn.readBuff, 0, count);
Console.WriteLine("收到 [" + conn.GetAdress() + "] 数据:" + str);
str = conn.GetAdress() + ":" + str;
byte[] bytes = System.Text.Encoding.Default.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 (Exception e)
{
Console.WriteLine("收到 [" + conn.GetAdress() + "] 断开链接");
conn.Close();
}
}
}
using UnityEngine;
using UnityEngine.UI;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System;
public class ClientWork : MonoBehaviour
{
//服务器IP和端口
public InputField hostInput;
public InputField portInput;
//显示客户端收到的消息
public Text recvText;
public string recvStr;
//显示客户端IP和端口
public Text clientText;
//聊天输入框
public InputField textInput;
//Socket和接收缓冲区
Socket socket;
const int BUFFER_SIZE = 1024;
public byte[] readBuff = new byte[BUFFER_SIZE];
//因为只有主线程能够修改UI组件属性
//因此在Update里更换文本
void Update()
{
recvText.text = recvStr;
}
//连接
public void Connetion()
{
if (null != socket) return;
//清理text
recvText.text = "";
//Socket
socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
//Connect
string host = hostInput.text;
int port = int.Parse(portInput.text);
socket.Connect(host, port);
clientText.text = socket.LocalEndPoint.ToString();
//Recv
socket.BeginReceive(readBuff, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCb, null);
}
//接收回调
private void ReceiveCb(IAsyncResult ar)
{
try
{
//count是接收数据的大小
int count = socket.EndReceive(ar);
//数据处理
string str = Encoding.UTF8.GetString(readBuff, 0, count);
if (recvStr.Length > 300) recvStr = "";
recvStr += str + "\n";
//继续接收
socket.BeginReceive(readBuff, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCb, null);
}
catch
{
recvText.text += "链接已断开";
socket.Close();
}
}
//发送数据
public void Send()
{
string str = textInput.text;
byte[] bytes = Encoding.UTF8.GetBytes(str);
try
{
socket.Send(bytes);
}
catch { }
}
}
238