Socket通讯主要分服务端和客户端,服务器端监听某个端口,客户端访问该端口,服务端检测到客户端访问后,则表示连接完成,然后就可以开始互相通讯了。
客户端代码示例:
/// <summary>
/// 初始化Socket
/// </summary>
/// <param name="ipAdderss"></param>
/// <param name="port"></param>
private static void OpenSocket()
{
//初始化
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket = socket;
//设置IP和端口
IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse('192.168.1.1'), 1202);
try
{
socket.Connect(iPEndPoint);
}
catch (Exception ex)
{
LoggerHelper.Error(ex, "OpenSocket");
return;
}
//接收信息
//ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveServerMsg), socket);
}
/// <summary>
/// 访问服务器,接收信息
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
public static string GetALCDate(string num)
{
try
{
lock (obj)
{
var result = "";
if (_socket is null || !_socket.Connected)
{
OpenSocket();
}
if (_socket.Connected)
{
//发送信息
byte[] data = Encoding.Default.GetBytes(num);
_socket.Send(data, 0, data.Length, SocketFlags.None);
result = ReceiveServerMsg();
if (!string.IsNullOrWhiteSpace(result))
{
ServerExit(_socket);
}
}
return result;
}
}
catch(Exception ex)
{
LoggerHelper.Error(ex, $"GetALCDate->");
return "";
}
}
/// <summary>
/// 接收服务器信息
/// </summary>
/// <param name="obj"></param>
private static string ReceiveServerMsg()
{
var proxSocket = _socket;
//创建缓存内存,存储接收的信息 ,不能放到while中,这块内存可以循环利用
byte[] data = new byte[1020 * 1024];
while (true)
{
//接收消息,返回字节长度
int len;
try
{
len = proxSocket.Receive(data, 0, data.Length, SocketFlags.None);
}
catch (Exception ex)
{
//关闭Socket
ServerExit(proxSocket);
return "";
}
if (len <= 0)
{
//关闭Socket
ServerExit(proxSocket);
return "";
}
string msgStr = Encoding.Default.GetString(data, 0, len);
return msgStr;
}
}
/// <summary>
/// 关闭连接
/// </summary>
/// <param name="proxSocket"></param>
private static void ServerExit(Socket proxSocket)
{
try
{
if (proxSocket.Connected)//如果是连接状态
{
proxSocket.Shutdown(SocketShutdown.Both);//关闭连接
proxSocket.Close(100);//100秒超时间
}
}
catch (Exception ex)
{
LoggerHelper.Error(ex, $"ServerExit->");
}
}
服务端代码示例:
/// <summary>
/// 服务端初始化
/// </summary>
private static void OpenServerSocket()
{
//1、创建Socket对象
//参数:寻址方式,当前为Ivp4 指定套接字类型 指定传输协议Tcp;
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2、绑定端口、IP
IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse('192.168.1.1'), 1202);
socket.Bind(iPEndPoint);
//3、开启侦听
socket.Listen(10);//如果同时来了100个连接请求,只能处理一个,队列中10个在等待连接的客户端,其他的则返回错误消息。
//4、开始接受客户端的连接
ThreadPool.QueueUserWorkItem(new WaitCallback(AcceptClientConnect), socket);
loadServer = 1;
}
/// <summary>
/// 线程池线程执行的接受客户端连接方法
/// </summary>
/// <param name="obj">传入的Socket</param>
private static void AcceptClientConnect(object obj)
{
//转换Socket
var serverSocket = obj as Socket;
//接受客户端的连接
while (true)
{
//5、创建一个负责通信的Socket
Socket proxSocket = serverSocket.Accept();
//将连接的Socket存入集合
clientScoketLis.Add(proxSocket);
//6、不断接收客户端发送来的消息
ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveClientMsg), proxSocket);
}
}
/// <summary>
/// 不断接收客户端信息子线程方法
/// </summary>
/// <param name="obj">参数Socke对象</param>
private static void ReceiveClientMsg(object obj)
{
var proxSocket = obj as Socket;
//创建缓存内存,存储接收的信息 ,不能放到while中,这块内存可以循环利用
byte[] data = new byte[1020 * 1024];
while (true)
{
int len = 0;
try
{
//接收消息,返回字节长度
len = proxSocket.Receive(data, 0, data.Length, SocketFlags.None);
}
catch (Exception ex)
{
LoggerHelper.Error(ex, $"ReceiveClientMsg->");
return;
}
if (len <= 0)//判断接收的字节数
{
return;
}
string msgStr = Encoding.Default.GetString(data, 0, len);
//储存到数据库
Task.Run(() =>
{
ALCDataToSqlData(msgStr);
});
}
}
/// <summary>
/// 消息发送事件
/// </summary>
private static void GetSendMsg(string num)
{
foreach (Socket proxSocket in clientScoketLis)
{
var clietIP = (proxSocket.RemoteEndPoint as IPEndPoint).Address;
try
{
byte[] data = Encoding.Default.GetBytes(num);
var i = proxSocket.Send(data, 0, data.Length, SocketFlags.None);
}
catch (Exception e)
{
LoggerHelper.Error(e, $"GetSendMsg(" + clietIP + ")->");
}
//if (proxSocket.Connected)//判断客户端是否还在连接
//{
// byte[] data = Encoding.Default.GetBytes(num);
// proxSocket.Send(data, 0, data.Length, SocketFlags.None);
//}
//else
//{
// clientScoketLis.Remove(proxSocket);
//}
}
}
/// <summary>
/// 客户端退出调用
/// </summary>
/// <param name="msg"></param>
private static void ClientExit(Socket proxSocket)
{
clientScoketLis.Remove(proxSocket);//移除集合中的连接Socket
try
{
if (proxSocket.Connected)//如果是连接状态
{
proxSocket.Shutdown(SocketShutdown.Both);//关闭连接
proxSocket.Close(100);//100秒超时间
}
}
catch (Exception ex)
{
}
}
/// <summary>
/// 推送数据库
/// </summary>
/// <param name="dtStr">ALC推送过来的数据</param>
private static void ALCDataToSqlData(string dtStr)
{
try
{
var ret = helper.ExecuteSql($@"insert into data.Data");
}
catch(Exception ex)
{
}
}