1、TCP/IP、UDP、Socket 概念:
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
UDP(User Data Protocol,用户数据报协议)是与 TCP 相对应的协议。它是属于TCP/IP协议族中的一种。
这里有一张图,表明了这些协议的关系。
注:TCP/IP协议 包括 传输层、网络层、链路层。
上图中没有 Socket 影子,请看下图:
Socket 是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
举个例子:一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。
先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。
总结:Socket 起源于 Unix,而 Unix/Linux 基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。
2、C# 实现 Socket 通讯:
首先引用命名空间:using System.Net; using System.Net.Sockets;
1️⃣ 客户端代码:
private static byte[] result = new byte[1024];
//设置服务器IP地址
IPAddress ip = IPAddress.Parse("127.0.0.1");
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
clientSocket.Connect(new IPEndPoint(ip, 1001));
Console.WriteLine("连接服务器成功!");
}
catch (Exception)
{
Console.WriteLine("连接服务器失败!");
}
//通过 clientSocket 接收数据
int receiveLength = clientSocket.Receive(result);
Console.WriteLine("接收到服务器消息:{0}", Encoding.ASCII.GetString(result, 0, receiveLength));
//通过 clientSocket 发送数据
for (int i = 0; i < 10; i++)
{
try
{
Thread.Sleep(2000);
string SendMsg = "客服端发送数据,时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
clientSocket.Send(Encoding.ASCII.GetBytes(SendMsg));
Console.WriteLine("向服务器端发送消息:{0}", SendMsg);
}
catch (Exception)
{
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
break;
}
}
Console.WriteLine("消息发送完毕!");
2️⃣ 服务端代码:
private static byte[] result = new byte[1024];
private static int ServicePort = 1001;
private static Socket ServiceSocket;
static void Main(string[] args)
{
//服务器IP
IPAddress ip = IPAddress.Parse("127.0.0.1");
ServiceSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ServiceSocket.Bind(new IPEndPoint(ip, ServicePort)); //绑定IP地址,端口
ServiceSocket.Listen(10); //设定最多10个排队连接请求
Thread th = new Thread(ListenClientConnect);
th.Start();
Console.WriteLine("启动监听{0}成功", ServiceSocket.LocalEndPoint.ToString());
Console.ReadLine();
}
/// <summary>
/// 监听客户端连接
/// </summary>
private static void ListenClientConnect()
{
while (true)
{
Socket clientSocket = ServiceSocket.Accept();
clientSocket.Send(Encoding.ASCII.GetBytes("Service say Hollo!"));
Thread th = new Thread(ReceiveMessage);
th.Start(clientSocket);
}
}
/// <summary>
/// 接收消息
/// </summary>
/// <param name="ClientSocket"></param>
private static void ReceiveMessage(object ClientSocket)
{
Socket myClientSocket = (Socket)ClientSocket;
while (true)
{
try
{
//通过 ClientSocket 接收数据
int ReceiveNumber = myClientSocket.Receive(result);
Console.WriteLine("接收到客户端{0}消息{1}", myClientSocket.RemoteEndPoint.ToString(), Encoding.ASCII.GetString(result));
}
catch (Exception)
{
Console.WriteLine("获取客户端消息失败!");
myClientSocket.Shutdown(SocketShutdown.Both);
myClientSocket.Close();
break;
}
}
}