Socket通信原理是一种“打开—读/写—关闭”模式的实现,服务器和客户端各自维护一个“文件”,在建立连接打开后,可以向文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件。
Socket在应用层和传输层之间的一个抽象层,它把 TCP/IP 层复杂的操作抽象为几个简单的接口,供应用层调用实现进程在网络中的通信。Socket 起源于 UNIX,在 UNIX 一切皆文件的思想下,进程间通信就被冠名为文件描述符(file descriptor)。
Socket 保证了不同计算机之间的通信,也就是网络通信。对于网站,通信模型是服务器与客户端之间的通信。两端都建立了一个 Socket 对象,然后通过 Socket 对象对数据进行传输。通常服务器处于一个无限循环,等待客户端的连接。
1. 什么是TCP/IP、UDP?
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的,TCP/IP协议族包括运输层、网络层、链路层。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
2. Socket是什么?
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
那么,如何利用C#创建一个服务端呢。
// 创建一个和客户端通信的套接字
static Socket socketwatch = null;
//定义一个集合,存储客户端信息
static Dictionary<string, Socket> clientConnectionItems = new Dictionary<string, Socket> { };
public static void Main(string[] args)
{
//定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议)
socketwatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Any;//获取IP
//此端口专门用来监听的
IPEndPoint point = new IPEndPoint(ip, 2333);
//监听绑定的网络节点
socketwatch.Bind(point);
//将套接字的监听队列长度限制为20
socketwatch.Listen(20);
//负责监听客户端的线程:创建一个监听线程
Thread threadwatch = new Thread(watchconnecting);
//将窗体线程设置为与后台同步,随着主线程结束而结束
threadwatch.IsBackground = true;
//启动线程
threadwatch.Start();
Console.ReadKey();
}
//监听客户端发来的请求
static void watchconnecting()
{
//持续不断监听客户端发来的请求
while(true)
{
Socket connection=null;
try
{
connection=socketwatch.Accept();//Accept,进行二次握手
}
catch(Exception ex)
{
Console.WriteLine(ex.Message)
break;
}
//获取客户端的IP以及端口
IPAddress clientIP = (connection.RemoteEndPoint as IPEndPoint).Address;
int clientPort= (connection.RemoteEndPoint as IPEndPoint).Port;
Console.WriteLine("IP为:"+clientIP+"连接成功");
//客户端网络结点号
string remoteEndPoint = connection.RemoteEndPoint.ToString();
//添加客户端信息
clientConnectionItems.Add(remoteEndPoint, connection);
IPEndPoint netpoint = connection.RemoteEndPoint as IPEndPoint;
//创建一个通信线程
ParameterizedThreadStart pts = new ParameterizedThreadStart(recv);
Thread thread = new Thread(pts);
//设置为后台线程,随着主线程退出而退出
thread.IsBackground = true;
//启动线程
thread.Start(connection);
}
}
//接收客户端发来的信息,客户端套接字对象
static void recv(object socketclientpara)
{
Socket socketServer = socketclientpara as Socket;
while(true)
{
//创建一个内存缓冲区,大小为1M
byte[] arrServerRecMsg=new byte[1024*1024]
//将接收到的信息存入到内存缓冲区,并返回其字节数组的长度
try
{
int length=socketServer.Receive(arrServerRecMsg)//获取长度
if(leng<=0)
break;
//将机器接收到的字节数组转换为人可以读懂的字符串
string strSRecMsg=Encoding.UTF8.GetString(arrServerRecMsg,0,length);
//调用业务逻辑处理方法
string info=AcceptedHL7Data(strSRecMsg)
//返回客户端信息
var isTrue = socketServer.Send(Encoding.UTF8.GetBytes(info));
}
catch(Exception ex)
{
Console.WriteLine("提示异常");
//关闭之前accept出来的客户端进行通信的套接字
socketServer.Close();
break;
}
}
}
//处理业务逻辑方法
public static string AcceptedHL7Data(string strHL7v2)
{
Console.WriteLine("处理业务逻辑");
return "";
}