C# Socket服务端及多客户端连接通信实现
服务端代码(控制台示例):
static List<Socket> Sockets = new List<Socket>();
static void Main(string[] args)
{
;
];
IPEndPoint localEP = new IPEndPoint(IPAddress.Any, port);
Socket listener = new Socket(localEP.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEP);
listener.Listen();
Console.WriteLine("等待客户端连接....");
while (true) //该操作用于多个客户端连接
{
Socket sc = listener.Accept();//接受一个连接
Sockets.Add(sc); //将连接的客户端, 添加到内存当中
Thread t = new Thread(new ThreadStart(() => ReceiveData(sc))); //开启当前Socket线程, 去执行获取数据的动作,与客户端通信
t.IsBackground = true;
t.Start();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.ReadLine();
}
public static void ReceiveData(Socket sc)
{
];
Console.WriteLine("接受到了客户端:" + sc.RemoteEndPoint.ToString() + "连接....");
//握手
int length = sc.Receive(buffer);//接受客户端握手信息
sc.Send(PackHandShakeData(GetSecKeyAccetp(buffer, length)));while (true)
{
try
{
//接受客户端数据
Console.WriteLine("等待客户端数据....");
length = sc.Receive(buffer);//接受客户端信息
string clientMsg = AnalyticData(buffer, length);
Console.WriteLine("接受到客户端数据:" + clientMsg);
//发送数据
string sendMsg = "服务端返回信息:" + clientMsg;
sc.Send(PackData(sendMsg));
}
catch (Exception ex)
{
Sockets.Remove(sc); //如果接收的过程中,断开, 那么内存中移除当前Socket对象, 并且退出当前线程
Console.WriteLine("客户端已经断开连接!");
return;
}
}
}
Socket 相关类
#region Socket Helper
/// <summary>
/// 打包握手信息
/// </summary>
/// <param name="secKeyAccept"></param>
/// <returns></returns>
private static byte[] PackHandShakeData(string secKeyAccept)
{
var responseBuilder = new StringBuilder();
responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + Environment.NewLine);
responseBuilder.Append("Upgrade: websocket" + Environment.NewLine);
responseBuilder.Append("Connection: Upgrade" + Environment.NewLine);
responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine + Environment.NewLine);
return Encoding.UTF8.GetBytes(responseBuilder.ToString());
}
/// <summary>
/// 生成Sec-WebSocket-Accept
/// </summary>
/// <param name="handShakeText">客户端握手信息</param>
/// <returns>Sec-WebSocket-Accept</returns>
private static string GetSecKeyAccetp(byte[] handShakeBytes, int bytesLength)
{
, bytesLength);
string key = string.Empty;
Regex r = new Regex(@"Sec\-WebSocket\-Key:(.*?)\r\n");
Match m = r.Match(handShakeText);
)
{
key = Regex.Replace(m.Value, @"Sec\-WebSocket\-Key:(.*?)\r\n", "$1").Trim();
}
byte[] encryptionString = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
return Convert.ToBase64String(encryptionString);
}
/// <summary>
/// 解析客户端数据包
/// </summary>
/// <param name="recBytes">服务器接收的数据包</param>
/// <param name="recByteLength">有效数据长度</param>
/// <returns></returns>
private static string AnalyticData(byte[] recBytes, int recByteLength)
{
) { return string.Empty; }
] & 0x80) == 0x80; // 1bit,1表示最后一帧
if (!fin)
{
return string.Empty;// 超过一帧暂不处理
}
] & 0x80) == 0x80; // 是否包含掩码
if (!mask_flag)
{
return string.Empty;// 不包含掩码的暂不处理
}
] & 0x7F; // 数据长度
];
byte[] payload_data;
)
{
Array.Copy(recBytes, , masks, , );
payload_len = (UInt16)(recBytes[] << | recBytes[]);
payload_data = new byte[payload_len];
Array.Copy(recBytes, , payload_data, , payload_len);
}
)
{
Array.Copy(recBytes, , masks, , );
];
; i < ; i++)
{
uInt64Bytes[i] = recBytes[ - i];
}
UInt64 len = BitConverter.ToUInt64(uInt64Bytes, );
payload_data = new byte[len];
; i < len; i++)
{
payload_data[i] = recBytes[i + ];
}
}
else
{
Array.Copy(recBytes, , masks, , );
payload_data = new byte[payload_len];
Array.Copy(recBytes, , payload_data, , payload_len);
}
; i < payload_len; i++)
{
payload_data[i] = (]);
}
return Encoding.UTF8.GetString(payload_data);
}
/// <summary>
/// 打包服务器数据
/// </summary>
/// <param name="message">数据</param>
/// <returns>数据包</returns>
private static byte[] PackData(string message)
{
byte[] contentBytes = null;
byte[] temp = Encoding.UTF8.GetBytes(message);
)
{
contentBytes = ];
contentBytes[] = 0x81;
contentBytes[] = (byte)temp.Length;
Array.Copy(temp, , contentBytes, , temp.Length);
}
else if (temp.Length < 0xFFFF)
{
contentBytes = ];
contentBytes[] = 0x81;
contentBytes[] = ;
contentBytes[] = (byte)(temp.Length & 0xFF);
contentBytes[] = ( & 0xFF);
Array.Copy(temp, , contentBytes, , temp.Length);
}
else
{
// 暂不处理超长内容
}
return contentBytes;
}
#endregion
客户端连接(网页测试):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebSockets客户端示例</title>
</head>
<script>
var webSocket;
function connect()
{
try
{
var readyState = new Array("正在连接","已建立连接","正在关闭连接","已关闭连接");
var host = "ws://localhost:10";
webSocket = new WebSocket(host);
var message = document.getElementById("message");
message.innerHTML +="<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
webSocket.onopen = function()
{
message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
}
webSocket.onmessage = function(msg)
{
message.innerHTML +="<p>接收信息:" + msg.data + "</p>";
}
webSocket.onclose=function()
{
message.innerHTML +="<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
}
}
catch(exception)
{
message.innerHTML += "<p>有错误发生</p>";
}
}
function send()
{
var text = document.getElementById("text").value;
var message = document.getElementById("message");
if(text == "")
{
message.innerHTML += "<p>请输入一些文字</p>";
return ;
}
try
{
webSocket.send(text);
message.innerHTML += "<p>发送数据:" +text + "</p>";
}
catch(exception)
{
message.innerHTML += "<p>发送数据出错</p>";
}
document.getElementById("text").value="";
}
function disconnect()
{
webSocket.close();
}
</script>
<body>
<h1>WebSocket客户端示例</h1>
<div id="message"></div>
<p>请输入一些文字</p>
<input id="text" type="text">
<button id="connect" onClick="connect();">建立连接</button>
<button id="send" onClick="send();">发送数据</button>
<button id="disconnect" onClick="disconnect();">断开连接</button>
</body>
</html>
应用效果:

C# Socket服务端及多客户端连接通信实现的更多相关文章
- MongoDB的基本操作:服务端启动,客户端连接,CRUD操作
本文内容: MongoDB的介绍 MongoDB服务端的启动 MongoDB客户端连接 SQL与MongoDB相关概念解释 什么是BSON 数据库操作 集合操作 文档操作 测试环境:win10 软件版 ...
- PHP socket服务端与客户端的简易通信
今天学习socket通信的同时,顺便整理了下以前初识socket的知识. 现在关于php的socket通信,有些框架已经十分成熟了,比如 swoole 和 workerman,这两个大家可以学习学习 ...
- Python3学习之路~8.3 socket 服务端与客户端
通过8.2的实例1-6,我们可以总结出来,socket的服务端和客户端的一般建立步骤: 服务端 步骤:1创建实例,2绑定,3监听,4阻塞,5发送&接收数据,6关闭. #Author:Zheng ...
- AutoCAD.net支持后台线程-Socket服务端
最近因为公司项目的需求,CAD作为服务端在服务器中常驻运行,等待客户端远程发送执行任务的指令,最终确认用Socket-tcp通讯,CAD需要实时监听客户端发送的消息,这时就需要开启线程执行Socket ...
- C# Socket服务端与客户端通信(包含大文件的断点传输)
步骤: 一.服务端的建立 1.服务端的项目建立以及页面布局 2.各功能按键的事件代码 1)传输类型说明以及全局变量 2)Socket通信服务端具体步骤: (1)建立一个Socket (2)接收 ...
- 利用多线程使socket服务端可以与多个客户端同时通讯
利用多线程使socket服务端可以与多个客户端同时通讯 server import socket 1. 符合TCP协议的手机 server = socket.socket(socket.AF_INET ...
- Socket探索1-两种Socket服务端实现
介绍 一次简单的Socket探索之旅,分别对Socket服务端的两种方式进行了测试和解析. CommonSocket 代码实现 实现一个简单的Socket服务,基本功能就是接收消息然后加上结束消息时间 ...
- 使用NewLife网络库构建可靠的自动售货机Socket服务端(一)
最近有个基于tcp socket 协议和设备交互需求,想到了新生命团队的各种组件,所以决定用NewLife网络库作为服务端来完成一系列的信息交互. 第一,首先说一下我们需要实现的功能需求吧 1,首先客 ...
- 在python中编写socket服务端模块(二):使用poll或epoll
在linux上编写socket服务端程序一般可以用select.poll.epoll三种方式,本文主要介绍使用poll和epoll编写socket服务端模块. 使用poll方式的服务器端程序代码: i ...
随机推荐
- 19.允许重复的unordered_map
#include <string> #include <iostream> //查询性能最高 //允许重复的,hash_map #include <unordered_m ...
- POJ 3190 priority_queue 贪心
思路: 贪心?就算是吧 先把所有的开始时间排个序 如果当前的能匹配上已有的牛栏,就找开始时间最早的那个. 否则新加一个牛栏 整个过程用priority_queue实现就OK了.. //By Siriu ...
- java 类和对象1
编写一个Java应用程序,该程序中有3个类:Lader.Circle和主类A.具体要求如下:Lader类具有类型为double的上底.下底.高.面积属性,具有返回面积的功能,包括一个构造方法对上底.下 ...
- Android RecyclerView 水平滚动+自动循环轮播
主要处理的地方: 1.RecyclerView中Adapter的item个人可以无限轮询. 2.RecyclerView自动滑动 3.手指按下时滑动停止,手指抬起后继续自动滑动 public clas ...
- OGG切换步骤
步骤描述 提前准备好切换方案:以及其他相关人员的配合 切换至容灾数据库: (1)停止前端业务,确认目标端数据已经追平 (2)数据校验,确认数据一致 (3)停止生产库OGG进程(停止后可以直接删除) ( ...
- GoldenGate 1403错误解决方法
OGG oracle goldengate 1403错误解决方法 1. 错误描述WARNING OGG-01154 Oracle GoldenGate Delivery for Oracle, re ...
- Zero-input latency scheduler: Scheduler Overhaul
Scheduler Overhaul, with contributions from rbyers, sadrul, rjkroege, sievers, epenner, skyostil, br ...
- Android chromium 2
Overview JNI (Java Native Interface) is the mechanism that enables Java code to call native function ...
- NOIP2013 货车运输 倍增
问题描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能 ...
- 容器配置https
生成秘钥库 通过jdk的keytool工具生成秘钥库 keytool -genkeypair -alias "localhost" -keyalg "RSA" ...