[置顶] C#中Socket服务端代码分享
最近在对项目中Socket通讯中的服务端代码进行优化,保证能接受尽可能多的客户端的连接,并且不会丢掉连接,不会掉数据包。经过一段时间的反复测试和修改,终于达到了这一要求。服务端代码采用了异步通讯的方式,并使用ManualResetEvent来对线程进行控制。在程序中,ManualResetEvent 的使用很关键。 ManualResetEvent 允许线程通过发信号互相通信。通常,此通信涉及一个线程在其他线程进行之前必须完成的任务。当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时,它调用 Reset 以将 ManualResetEvent 置于非终止状态,此线程可被视为控制 ManualResetEvent。调用 ManualResetEvent 上的 WaitOne 的线程将阻止,并等待信号。当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。一旦它被终止,ManualResetEvent 将保持终止状态(即对 WaitOne 的调用的线程将立即返回,并不阻塞),直到它被手动重置。可以通过将布尔值传递给构造函数来控制 ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则为 false。现在贴出主要的代码,欢迎大家指正,代码如下所示:
void ButtonStartListenClick(object sender, System.EventArgs e)
{
try
{
// Check the port value
if(textBoxPort.Text == "")
{
MessageBox.Show("Please enter a Port Number");
return;
}
if (txtConnectNum.Text.Trim() != "")
{
iConnectNum = int.Parse(txtConnectNum.Text.Trim());
Flage = 0;
}
else
{
MessageBox.Show("Please enter a Connect Number");
return;
}
string portStr = textBoxPort.Text;
int port = System.Convert.ToInt32(portStr);
// Create the listening socket...
m_mainSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint (IPAddress.Any, port);
// Bind to local IP Address...
m_mainSocket.Bind( ipLocal );
// Start listening...
m_mainSocket.Listen(10000);
// Set the event to nonsignaled state.设置无信号状态的事件
allDone.Reset();
// Create the call back for any client connections...
m_mainSocket.BeginAccept(new AsyncCallback (OnClientConnect), null);
// Wait until a connection is made before continuing.等待连接创建后继续
allDone.WaitOne();
UpdateControls(true);
}
catch(SocketException se)
{
MessageBox.Show ( se.Message );
}
}
// This is the call back function, which will be invoked when a client is connected
public void OnClientConnect(IAsyncResult asyn)
{
try
{
//让它继续处理并建立与客户端的连接
allDone.Set();
// Here we complete/end the BeginAccept() asynchronous call
// by calling EndAccept() - which returns the reference to
// a new Socket object
Socket workerSocket = m_mainSocket.EndAccept (asyn);
// Now increment the client count for this client
// in a thread safe manner
Interlocked.Increment(ref m_clientCount);
if (m_clientCount == 1)
{
lock (this)
{
stopwatch.Start();
dtStart = DateTime.Now;
writeLog("Server Start Socket Connect Time"+dtStart.ToString("yyyy-MM-dd HH:mm:ss fff"));
}
}
// Add the workerSocket reference to our ArrayList
m_workerSocketList.Add(workerSocket);
// Send a welcome message to client
string msg = "Welcome client " + m_clientCount + "\n";
SendMsgToClient(msg, m_clientCount);
// Update the list box showing the list of clients (thread safe call)
UpdateClientListControl();
// Let the worker Socket do the further processing for the
// just connected client
WaitForData(workerSocket, m_clientCount);
// Since the main Socket is now free, it can go back and wait for
// other clients who are attempting to connect
m_mainSocket.BeginAccept(new AsyncCallback ( OnClientConnect ),null);
// Wait until a connection is made before continuing.等待连接创建后继续
allDone.WaitOne();
}
catch(ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0,"1","\n OnClientConnection: Socket has been closed\n");
}
catch(SocketException se)
{
MessageBox.Show ( se.Message );
}
}
public class SocketPacket
{
// Constructor which takes a Socket and a client number
public SocketPacket(System.Net.Sockets.Socket socket, int clientNumber)
{
m_currentSocket = socket;
m_clientNumber = clientNumber;
}
public System.Net.Sockets.Socket m_currentSocket;
public int m_clientNumber;
// Buffer to store the data sent by the client
public byte[] dataBuffer = new byte[1024];
}
// Start waiting for data from the client
public void WaitForData(System.Net.Sockets.Socket soc, int clientNumber)
{
try
{
if ( pfnWorkerCallBack == null )
{
// Specify the call back function which is to be
// invoked when there is any write activity by the
// connected client
pfnWorkerCallBack = new AsyncCallback (OnDataReceived);
}
SocketPacket theSocPkt = new SocketPacket (soc, clientNumber);
//receiveDone.Reset();
soc.BeginReceive (theSocPkt.dataBuffer, 0,
theSocPkt.dataBuffer.Length,
SocketFlags.None,
pfnWorkerCallBack,
theSocPkt);
//receiveDone.WaitOne();
}
catch(SocketException se)
{
MessageBox.Show (se.Message );
}
}
// This the call back function which will be invoked when the socket
// detects any client writing of data on the stream
public void OnDataReceived(IAsyncResult asyn)
{
SocketPacket socketData = (SocketPacket)asyn.AsyncState ;
try
{
// Complete the BeginReceive() asynchronous call by EndReceive() method
// which will return the number of characters written to the stream
// by the client
//receiveDone.Set();
int iRx = socketData.m_currentSocket.EndReceive (asyn);
char[] chars = new char[iRx + 1];
// Extract the characters as a buffer
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(socketData.dataBuffer,
0, iRx, chars, 0);
System.String szData = new System.String(chars);
string msg = "" + socketData.m_clientNumber + ":";
AppendToRichEditControl(msg + szData);
//writeFromClientsMsgLog(msg + szData);
// Send back the reply to the client
string replyMsg = "Server Reply:" + szData.ToUpper();
// Convert the reply to byte array
byte[] byData = System.Text.Encoding.ASCII.GetBytes(replyMsg);
Socket workerSocket = (Socket)socketData.m_currentSocket;
workerSocket.Send(byData);
if (m_clientCount == iConnectNum && Flage == 0)
{
Interlocked.Increment(ref Flage);
string msgTime = "Server End Socket Action Time:";
lock(this)
{
stopwatch.Stop();
//lblTime.Text = stopwatch.Elapsed.Seconds.ToString();
int itime = stopwatch.Elapsed.Milliseconds;
//msgTime += stopwatch.Elapsed.Seconds.ToString()+"--"+itime.ToString();
msgTime += DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff");
}
writeLog(msgTime);
writeClientConnectionLog();
//UpdateLabelTime(msgTime);
//byData = System.Text.Encoding.ASCII.GetBytes(msgTime);
//workerSocket.Send(byData);
}
// Continue the waiting for data on the Socket
WaitForData(socketData.m_currentSocket, socketData.m_clientNumber );
}
catch (ObjectDisposedException )
{
System.Diagnostics.Debugger.Log(0,"1","\nOnDataReceived: Socket has been closed\n");
}
catch(SocketException se)
{
if(se.ErrorCode == 10054) // Error code for Connection reset by peer
{
string msg = "Client " + socketData.m_clientNumber + " Disconnected" + "\n";
AppendToRichEditControl(msg);
//writeFromClientsMsgLog(msg);
// Remove the reference to the worker socket of the closed client
// so that this object will get garbage collected
m_workerSocketList[socketData.m_clientNumber - 1] = null;
UpdateClientListControl();
}
else
{
MessageBox.Show (se.Message );
}
}
}
void CloseSockets()
{
if(m_mainSocket != null)
{
m_mainSocket.Close();
}
Socket workerSocket = null;
for(int i = 0; i < m_workerSocketList.Count; i++)
{
workerSocket = (Socket)m_workerSocketList[i];
if(workerSocket != null)
{
workerSocket.Close();
workerSocket = null;
}
}
}
void SendMsgToClient(string msg, int clientNumber)
{
// Convert the reply to byte array
byte[] byData = System.Text.Encoding.ASCII.GetBytes(msg);
Socket workerSocket = (Socket)m_workerSocketList[clientNumber - 1];
//workerSocket.Send(byData);
workerSocket.BeginSend(byData, 0, byData.Length, 0,
new AsyncCallback(SendCallback), workerSocket);
}
private void SendCallback(IAsyncResult asyn)
{
Socket client = (Socket)asyn.AsyncState;
// 完成数据发送.
int bytesSent = client.EndSend(asyn);
}
完整的代码可以在我的资源中下载到,资源的名称为C#中Socket服务端通讯的代码。
转载于:https://www.cnblogs.com/kevinGao/archive/2011/12/14/2776054.html
[置顶] C#中Socket服务端代码分享相关推荐
- java web启动socket_javaweb启动时启动socket服务端代码实现
这篇文章主要介绍了javaweb启动时启动socket服务端代码实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 说明:在javaweb项目启动的 ...
- 在云服务器搭建 socket服务端
1.环境:腾讯云服务器.ubuntu16.python3.git 2.在自己电脑(我的win10)用python3写好socket服务端代码,上传到自己的GitHub,然后在云服务器里git clon ...
- git钩子放服务器_使用 git post-receive 钩子部署服务端代码
在 git 中提交服务器源码的时候,如果能够直接更新到测试服务器,并且重启服务使其生效,会节省懒惰的程序员们大量的时间. git 的 Server-side hook (服务端钩子/挂钩)可以用来做件 ...
- 【★更新★】高性能 Windows Socket 服务端与客户端组件(HP-Socket v2.0.1 源代码及测试用例下载)...
HP-Socket 以前为某大型通信项目开发了一套通用 Windows Socket TCP 底层通信组件,组件代号为 HP-Socket.现在把 HP-Socket 的所有代码向大众公开,希望能对大 ...
- Python 套接字-判断socket服务端有没有关闭的方法实例演示,查看socket运行状态
通过 getattr(socket, '_closed') 的返回值可以判断服务端的运行状态. True 是关闭状态,False 是运行中. 实例代码展示: import socketip = 'lo ...
- C# Socket服务端与客户端通信(包含大文件的断点传输)
步骤: 一.服务端的建立 1.服务端的项目建立以及页面布局 2.各功能按键的事件代码 1)传输类型说明以及全局变量 2)Socket通信服务端具体步骤: (1)建立一个Socket (2)接收 ...
- Java高级补充(Socket服务端、客户端)、Handler类、安卓Socket传数据、WebView
Socket服务端简单地API: 主要用到以下几个API:ServerSocket用来设置端口号.accept用来和服务端连接.getInputStream用来获取输入流.read用来读取输入流里面的 ...
- 《零基础看得懂的C语言入门教程 》——(十三)socket服务端编写
一.学习目标 了解C语言的socket的概念 了解C语言socket的使用方法 完成C语言socket服务端 目录 C语言真的很难吗?那是你没看这张图,化整为零轻松学习C语言. 第一篇:(一)脱离学习 ...
- android socket 服务端,Android socket 服务端
Android socket 服务端 Android 想在Android 上跑一个 socket 服务端.把在java工程里运行起来的代码直接放到android项目里来,开启线程,创建ServerSo ...
最新文章
- mac-address-table static命令的使用
- python网上有免费资源吗_【转载】学习Python无从下手?最好的免费资源想要拿走...
- 数据挖掘 —— 模型评估
- 【编程语言】Ruby完全自学手册
- 使用OpenExif修改jpeg图片信息
- @property 的属性class
- MMP,我说每年年会我怎么老是中不了奖,原来是这样
- 在互联网时代如何工作得更简单
- 【C语言】乘法口诀表
- 最简单24点算法,可任意实现n数n点,一看就明!
- 典型行业大数据应用和安全风险和解决方案
- Visual studio 无法打开源文件的问题或系统找不到指定文件
- mount的挂载远程服务器文件夹
- android外接USB扫码器应用闪退,外接U盘正常的情况
- bwiki样式的活动倒计时html代码(带渐变色进度条)
- windows 7z windows cannot create symbolic link : 客户端没有所需的特权。
- 中国人民大学与加拿大女王大学金融硕士——在这里,打开精彩“识界”
- 苹果Apple Pay优缺点全解析
- 计算机存在其他连接设备错误,USB设备连接电脑失败怎么办
- dsp调音一次多少钱_dsp调音技巧
热门文章
- formValidator的一些验证实例
- Spring学习(五)bean装配详解之 【XML方式配置】
- step3 . day2 数据结构之线性表链表
- 开发时对业务技术框架的理解
- 2018第九届蓝桥杯省赛真题 C语言B组 第一题
- form表单的onsubmit()问题 集合
- BG.Hive - part1
- ASP.NET Core中如影随形的”依赖注入”[上]: 从两个不同的ServiceProvider说起
- CSS自学笔记(16):CSS3 用户界面
- 用docker安装mysql5-6,并远程连接