以一些示例,记录 C# 中如何使用Socket:
目录
1.第一个示例,使用.net 自带的 Socket 纯手工写 (Udp协议)
2.第二个示例,使用.net 自带的 Socket 纯手工写 (Tcp协议)
1.第一个示例,使用.net 自带的 Socket 纯手工写 (Udp协议)
这个方式灵活性高,但不建议使用:
这个示例的作用是:服务端和客户端,可以互相收发消息,如上图。我用的本机测试的,所以用了两个端口来监听。如果是不同机器且连着内网或公网,只需一个监听端口,但要换成对应的局域网ip或者公网映射ip.
步骤:
1.新增个空解决方案,并添加两个winform项目,一个是 server 端一个是 client 端:
2.在服务端和客户端分别加入如下代码:
服务端:
public partial class Server : Form
{
private readonly Socket _listenSocket;
private EndPoint _listenPort = new IPEndPoint(IPAddress.Any, 7942);
private EndPoint _testClientPort = new IPEndPoint(IPAddress.Parse("192.168.2.32"), 7943);
//数据
private byte[] _buffer = new byte[1024];
//数据(字符串)
private string _chatString = string.Empty;
//客户端ip+端口
private EndPoint _clientIpPort;
//定个委托
public delegate void ShowDataDelegate();
public Server()
{
InitializeComponent();
_listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
_listenSocket.Bind(_listenPort);//本机用Bind,远程用Connect
_listenSocket.BeginReceiveFrom(_buffer, 0, 1024, SocketFlags.None, ref _listenPort, ReceiveData, _listenSocket);
}
private void ShowData()
{
if (!string.IsNullOrEmpty(_chatString))
{
this.richTextBox.AppendText($"客户端({_clientIpPort}): {_chatString}\n");
}
}
private void ReceiveData(IAsyncResult ar)
{
// 创建ip+port
var sender = new IPEndPoint(IPAddress.Any, 0);
var tempRemoteEp = (EndPoint)sender;
//获取socket
var socket = (Socket)ar.AsyncState;
//获取客户端发来的数据(客户端ip+port在第二个参数中)
var recv = socket.EndReceiveFrom(ar, ref tempRemoteEp);
//客户端ip+端口
_clientIpPort = tempRemoteEp;
//将数据流转成字符串
_chatString = Encoding.Unicode.GetString(_buffer, 0, recv);
richTextBox.Invoke(new ShowDataDelegate(ShowData));
if (!this.IsDisposed)
{
_listenSocket.BeginReceiveFrom(_buffer, 0, 1024, SocketFlags.None, ref _listenPort, ReceiveData, _listenSocket);
}
}
private void button1_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(textBox1.Text))
{
var newSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
var response = Encoding.Unicode.GetBytes(textBox1.Text);
newSocket.SendTo(response, 0, response.Length, SocketFlags.None, _testClientPort);
this.richTextBox.AppendText($"服务器(本地): {textBox1.Text}\n");
}
}
}
客户端:
public partial class Client : Form
{
//客户端用来接收数据的socket
private readonly Socket _listenSocket;
private EndPoint _listenPort = new IPEndPoint(IPAddress.Parse("192.168.2.32"), 7943);
private readonly EndPoint _serverPort = new IPEndPoint(IPAddress.Parse("192.168.2.32"), 7942);
//保存聊天信息
private readonly byte[] _buffer = new byte[1024];
//保存服务器地址
private EndPoint _serverIpPort;
//收到的数据(字符串)
private string _receiveData = string.Empty;
//定义委托
private delegate void ShowDataDelegate();
public Client()
{
InitializeComponent();
//获取服务端聊天信息
_listenSocket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp);
_listenSocket.Bind(_listenPort);
_listenSocket.BeginReceiveFrom(_buffer, 0, 1024, SocketFlags.None, ref _listenPort, new AsyncCallback(ReceiveData), _listenSocket);
}
private void ShowData()
{
if (!string.IsNullOrEmpty(_receiveData))
{
this.richTextBox.AppendText($"服务器({_serverIpPort}): {_receiveData}\n");
}
}
private void ReceiveData(IAsyncResult ar)
{
// 创建ip+port
var sender = new IPEndPoint(IPAddress.Any, 0);
var tempRemoteEp = (EndPoint)sender;
//获取socket
Socket remote = (Socket)ar.AsyncState;
//获取服务端发来的数据(服务端ip+port在第二个参数中)
var recv = remote.EndReceiveFrom(ar, ref tempRemoteEp);
//服务端ip+端口
_serverIpPort = tempRemoteEp;
//将数据流转成字符串
_receiveData = Encoding.Unicode.GetString(_buffer, 0, recv);
//刷新界面数据
this.richTextBox.Invoke(new ShowDataDelegate(ShowData));
if (!this.IsDisposed)
{
_listenSocket.BeginReceiveFrom(_buffer, 0, 1024, SocketFlags.None, ref _listenPort, new AsyncCallback(ReceiveData), _listenSocket);
}
}
private void button_send_Click(object sender, EventArgs e)
{
SendDataToServer();
}
private void SendDataToServer()
{
if (!string.IsNullOrEmpty(this.textBox_sendInfo.Text))
{
//创建udp socket
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
var dataArray = Encoding.Unicode.GetBytes(this.textBox_sendInfo.Text);
//发送至服务端
socket.SendTo(dataArray, 0, dataArray.Length, SocketFlags.None, _serverPort);
this.richTextBox.AppendText($"客户端(本地): {this.textBox_sendInfo.Text}\n");
}
}
}
剩下的界面控件,直接去工具箱拖出来改成和代码对应的name即可,或者直接到这下载https://download.csdn.net/download/sudazf/86245369
2.第二个示例,使用.net 自带的 Socket 纯手工写 (Tcp协议)
同上,分别加入服务端和客户端代码:
服务端:
public partial class Server : Form
{
//建立连接后的Socket实例
private Socket _socket;
//定个委托
public delegate void ShowDataDelegate(string data);
public Server()
{
InitializeComponent();
//创建接收客户端消息的socket
var listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
listenSocket.Bind(new IPEndPoint(IPAddress.Any, 7942));
listenSocket.Listen(10);
Task.Run(() =>
{
_socket = listenSocket.Accept();
byte[] receive = new byte[1024];
while (true)
{
_socket.Receive(receive);
var data = Encoding.Unicode.GetString(receive);
this.richTextBox.Invoke(new ShowDataDelegate(ShowData), data);
}
});
}
private void ShowData(string data)
{
if (!string.IsNullOrEmpty(data))
{
this.richTextBox.AppendText($"客户端({_socket.RemoteEndPoint}): {data}");
this.richTextBox.AppendText("\n");
}
}
private void button1_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(textBox1.Text))
{
byte[] data = Encoding.Unicode.GetBytes(this.textBox1.Text);
_socket.SendTo(data, 0, data.Length, SocketFlags.None, _socket.RemoteEndPoint);
this.richTextBox.AppendText($"服务器(本地): {textBox1.Text}\n");
}
}
}
客户端:
public partial class Client : Form
{
//客户端用来接收数据的socket
private readonly Socket _listenSocket;
//服务器地址
private readonly EndPoint _serverAddress = new IPEndPoint(IPAddress.Parse("192.168.2.32"), 7942);
//定义委托
private delegate void ShowDataDelegate(string data);
public Client()
{
InitializeComponent();
_listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_listenSocket.Connect(_serverAddress);
Task.Run(() =>
{
byte[] receive = new byte[1024];
while (true)
{
_listenSocket.Receive(receive);
var data = Encoding.Unicode.GetString(receive);
this.richTextBox.Invoke(new ShowDataDelegate(ShowData), data);
}
});
}
private void ShowData(string data)
{
if (!string.IsNullOrEmpty(data))
{
this.richTextBox.AppendText($"服务器({_listenSocket.RemoteEndPoint}): {data}");
this.richTextBox.AppendText("\n");
}
}
private void button_send_Click(object sender, EventArgs e)
{
SendDataToServer();
}
private void SendDataToServer()
{
if (!string.IsNullOrEmpty(this.textBox_sendInfo.Text))
{
var dataArray = Encoding.Unicode.GetBytes(this.textBox_sendInfo.Text);
_listenSocket.SendTo(dataArray, 0, dataArray.Length, SocketFlags.None, _serverAddress);
this.richTextBox.AppendText($"客户端(本地): {this.textBox_sendInfo.Text}\n");
}
}
}
或者直接到这里下载https://download.csdn.net/download/sudazf/86245419
3.第三个示例,直接使用WebSocket【推荐使用】
使用WebSocket方法有很多种,这里记录几种:
为了简便示例,服务端就使用 Fleck
开源地址在 GitHub - statianzo/Fleck: C# Websocket Implementation
服务端代码:
static void Main(string[] args)
{
FleckLog.Level = LogLevel.Debug;
var allSockets = new List<IWebSocketConnection>();
var server = new WebSocketServer("ws://0.0.0.0:8181");
server.Start(socket =>
{
socket.OnOpen = () =>
{
Console.WriteLine("Open!");
allSockets.Add(socket);
};
socket.OnClose = () =>
{
Console.WriteLine("Close!");
allSockets.Remove(socket);
};
socket.OnMessage = message =>
{
Console.WriteLine(message);
allSockets.ToList().ForEach(s => s.Send("Echo: " + message));
};
});
var input = Console.ReadLine();
while (input != "exit")
{
foreach (var socket in allSockets.ToList())
{
socket.Send(input);
}
input = Console.ReadLine();
}
}
客户端就有很多种了:
比如直接用Chrome console终端:
或者直接前端javascript
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>websocket client</title>
<script type="text/javascript">
var start = function () {
var inc = document.getElementById('incomming');
var wsImpl = window.WebSocket || window.MozWebSocket;
var form = document.getElementById('sendForm');
var input = document.getElementById('sendText');
inc.innerHTML += "connecting to server ..<br/>";
// create a new websocket and connect
window.ws = new wsImpl('ws://localhost:8181/');
// when data is comming from the server, this metod is called
ws.onmessage = function (evt) {
inc.innerHTML += evt.data + '<br/>';
};
// when the connection is established, this method is called
ws.onopen = function () {
inc.innerHTML += '.. connection open<br/>';
};
// when the connection is closed, this method is called
ws.onclose = function () {
inc.innerHTML += '.. connection closed<br/>';
}
form.addEventListener('submit', function(e){
e.preventDefault();
var val = input.value;
ws.send(val);
input.value = "";
});
}
window.onload = start;
</script>
</head>
<body>
<form id="sendForm">
<input id="sendText" placeholder="Text to send" />
</form>
<pre id="incomming"></pre>
</body>
</html>
再或者使用微软自带的 ClientWebSocket
public partial class MainWindow : Window
{
private ClientWebSocket _webSocket;
private CancellationToken _cancellation;
public MainWindow()
{
InitializeComponent();
Init();
}
private async Task<int> Init()
{
_webSocket = new ClientWebSocket();
_cancellation = new CancellationToken();
await _webSocket.ConnectAsync(new Uri("ws://127.0.0.1:8181/"), _cancellation);
return 1;
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
var send = System.Text.Encoding.UTF8.GetBytes("Hello,女神在吗?");
await _webSocket.SendAsync(new ArraySegment<byte>(send), WebSocketMessageType.Text, true, _cancellation);
byte[] rec = new byte[1024];
await _webSocket.ReceiveAsync(new ArraySegment<byte>(rec), _cancellation);
string str = System.Text.Encoding.UTF8.GetString(rec);
MessageBox.Show(str);
}
}
个人觉推荐还是用下面的 WebSocket4Net,简单好用
private static WebSocket _websocketClient;
static void Main(string[] args)
{
try
{
_websocketClient = new WebSocket("ws://192.168.1.173:8181/");
_websocketClient.Opened += Websocket_Opened;
_websocketClient.Closed += WebsocketClient_Closed;
_websocketClient.Error += WebsocketClient_Error;
_websocketClient.Open();
Console.Read();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static void Websocket_Opened(object sender, EventArgs e)
{
Console.WriteLine("Opened");
_websocketClient.Send("Hello world!");
}
private static void WebsocketClient_Closed(object sender, EventArgs e)
{
Console.WriteLine("Closed");
}
private static void WebsocketClient_Error(object sender, SuperSocket.ClientEngine.ErrorEventArgs e)
{
Console.WriteLine($"Error: {e.Exception.Message}");
}