知道Socket原理,但是一直没有在代码里面尝试怎么操作,闲来无事实现了一个初步的Socket服务器和客户端连接的Demo,但是没有实现更高级一点的系列化传输,加解密处理以及队列和断线重连等处理,感兴趣的话可以自己再尝试尝试。
主要分服务器Socket和客户端Socket,只用了简单的字符串转byte[]的传递测试收发消息。
服务器这边的话实现了个初步的SocketID管理。
分ServerSocket和ClientSocket来具体实现服务器与客户端的收发逻辑。
ServerSocket的实现,单独启个工程。
namespace ServerSocket
{
class Program
{
private static ServerSocketDemo _serverSocket = null;
static void Main(string[] args)
{
_serverSocket = new ServerSocketDemo();
_serverSocket.Initialize(OnReceiveMsgCallback);
}
private static void OnReceiveMsgCallback(int socketId, string msg)
{
if (!string.IsNullOrEmpty(msg))
{
//给所有已连接的客户端发送消息,类似于广播
if (msg.Contains("all"))
{
_serverSocket.SendMsgToAll("嘿嘿嘿");
}
//只给当前发送消息来的客户端回消息,点对点
if (msg.Contains("single"))
{
_serverSocket.SendMsgByID(socketId, string.Format("你好,{0},收到了你的消息!", socketId));
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace ServerSocket
{
public class ServerSocketDemo
{
//IP和端口
private string IP = "127.0.0.1";
private int PORT = 9527;
private Socket _serverSocket = null;
//收取数据的缓冲区,每次读取多少数据的缓存
private byte[] _receiveBuff = new byte[1024];
//用来处理ClientSocket的ID
private int _socketID = 0;
//已连接的客户端Socket
private Dictionary<int, SocketInfo> _sockets = null;
//收到客户端消息的回调
private Action<int, string> _onReceiveMsgCall = null;
public void Initialize(Action<int, string> receiveMsgCall)
{
_onReceiveMsgCall = receiveMsgCall;
_sockets = new Dictionary<int, SocketInfo>();
//绑定IP和端口,启动Socket
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAddress = IPAddress.Parse(IP);
IPEndPoint ipEndpoint = new IPEndPoint(ipAddress, PORT);
_serverSocket.Bind(ipEndpoint);
_serverSocket.Listen(20);
Console.WriteLine(string.Format("ServerSocket:{0}启动成功!", _serverSocket.LocalEndPoint.ToString()));
//开个线程接收客户端的消息
Thread socketTread = new Thread(new ThreadStart(OnClientConnected));
socketTread.IsBackground = true;
socketTread.Start();
Console.ReadKey();
}
private void OnClientConnected()
{
while (true)
{
Socket clientSocket = _serverSocket.Accept();
Console.WriteLine(string.Format("{0}连接成功!", clientSocket.LocalEndPoint.ToString()));
Thread receiveThread = new Thread(OnReceiveMsg);
receiveThread.IsBackground = true;
//给客户端Socket生成ID并且记录客户端Socket的连接
SocketInfo socketInfo = new SocketInfo();
_socketID++;
socketInfo.ID = _socketID;
socketInfo.ClientSocket = clientSocket;
//把连接上的Socket保存起来
_sockets.Add(socketInfo.ID, socketInfo);
receiveThread.Start(socketInfo);
}
}
private void OnReceiveMsg(object info)
{
SocketInfo socketInfo = info as SocketInfo;
Socket receiveSocket = socketInfo.ClientSocket;
while (true)
{
try
{
//读取客户端发来的数据,这里没考虑类的系列化,只简单测试字符串的收发
int recvLen = receiveSocket.Receive(_receiveBuff);
string content = Encoding.UTF8.GetString(_receiveBuff, 0, recvLen);
Console.WriteLine(string.Format("收到用户【{0}】发来的消息:{1}", socketInfo.ID, content));
//做个回调,处理收到的数据
if (_onReceiveMsgCall != null)
{
_onReceiveMsgCall(socketInfo.ID, content);
}
}
catch (Exception ex)
{
Console.WriteLine("接收消息异常:" + ex.Message);
receiveSocket.Shutdown(SocketShutdown.Both);
receiveSocket.Close();
return;
}
}
}
/// <summary>
/// 根据记录的客户端SocketID进行单点的消息发送
/// </summary>
/// <param name="socketId"></param>
/// <param name="msg"></param>
public void SendMsgByID(int socketId, string msg)
{
if (_sockets.ContainsKey(socketId))
{
Socket clientSocket = _sockets[socketId].ClientSocket;
if (clientSocket.Connected)
{
byte[] bytes = Encoding.UTF8.GetBytes(msg);
clientSocket.Send(bytes);
}
}
}
/// <summary>
/// 发送给所有已连接的客户端
/// </summary>
/// <param name="msg"></param>
public void SendMsgToAll(string msg)
{
var iter = _sockets.GetEnumerator();
while (iter.MoveNext())
{
byte[] bytes = Encoding.UTF8.GetBytes(msg);
iter.Current.Value.ClientSocket.Send(bytes);
}
}
private class SocketInfo
{
/// <summary>
/// 记录Socket的ID
/// </summary>
public int ID { get; set; }
/// <summary>
/// 客户端的Socket连接
/// </summary>
public Socket ClientSocket { get; set; }
}
}
}
ClientSocket的实现
using System;
namespace ClientSocket
{
class Program
{
static void Main(string[] args)
{
ClientSocketDemo clientSocket = new ClientSocketDemo();
clientSocket.Initialize();
clientSocket.SendMsg("你好!");
while (true)
{
//输入数据按回车给服务器发消息
string newMsg = Console.ReadLine();
clientSocket.SendMsg(newMsg);
}
}
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace ClientSocket
{
public class ClientSocketDemo
{
private string IP = "127.0.0.1";
private int PORT = 9527;
private Socket _clientSocket = null;
private byte[] _buffer = null;
public void Initialize()
{
_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_buffer = new byte[1024];
IPAddress ip = IPAddress.Parse(IP);
IPEndPoint endPoint = new IPEndPoint(ip, PORT);
try
{
_clientSocket.Connect(endPoint);
Console.WriteLine(string.Format("连接{0}服务器成功!", _clientSocket.LocalEndPoint.ToString()));
}
catch (Exception ex)
{
Console.WriteLine(string.Format("连接服务器失败:\n"+ ex.Message));
return;
}
//开线程接收服务器下来的数据
Thread receiveThread = new Thread(OnReceiveMsg);
receiveThread.IsBackground = true;
receiveThread.Start();
}
/// <summary>
/// 接收服务器消息
/// </summary>
private void OnReceiveMsg()
{
while (true)
{
try
{
int receiveLen = _clientSocket.Receive(_buffer);
string receiveMsg = Encoding.UTF8.GetString(_buffer, 0, receiveLen);
Console.WriteLine(string.Format("收到服务器消息:" + receiveMsg));
}
catch (Exception ex)
{
Console.WriteLine("接收消息异常:\n" + ex.Message);
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Dispose();
Console.ReadKey();
}
}
}
/// <summary>
/// 给服务器发消息
/// </summary>
public void SendMsg(string msg)
{
if (_clientSocket != null && _clientSocket.Connected)
{
_clientSocket.Send(Encoding.UTF8.GetBytes(msg));
}
}
}
}
测试:
先启动ServerSocket,然后启动两个ClientSocket.
客户端给服务器发all代表广播给所有客户端,给服务器发single代表只点对点的进行回消息。
测试结果如下:
文章来源:https://www.toymoban.com/news/detail-598465.html
文章来源地址https://www.toymoban.com/news/detail-598465.html
到了这里,关于C#实现Socket的消息收发,ServerSocket,ClientSocket的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!