(转)C# Socket异步通信
本文转载自:http://www.cnblogs.com/llllll/archive/2009/05/13/1455703.html
服务器端
TCPServer
1、使用的通讯通道:socket
2、用到的基本功能:
Bind,
Listen,
BeginAccept
EndAccept
BeginReceive
EndReceive
3、函数参数说明
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
新建socket所使用的参数均为系统预定义的量,直接选取使用。
listener.Bind(localEndPoint);
localEndPoint 表示一个定义完整的终端,包括IP和端口信息。
//new IPEndPoint(IPAddress,port)
//IPAdress.Parse("192.168.1.3")
listener.Listen(100);
监听
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
AsyncCallback(AcceptCallback),一旦连接上后的回调函数为AcceptCallback。当系统调用这个函数时,自动赋予的输入参数为IAsyncResoult类型变量ar。
listener,连接行为的容器。
Socket handler = listener.EndAccept(ar);
完成连接,返回此时的socket通道。
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
接收的字节,0,字节长度,0,接收时调用的回调函数,接收行为的容器。
========
容器的结构类型为:
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
容器至少为一个socket类型。
===============
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
完成一次连接。数据存储在state.buffer里,bytesRead为读取的长度。
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
发送数据byteData,回调函数SendCallback。容器handler
int bytesSent = handler.EndSend(ar);
发送完毕,bytesSent发送字节数。
4 程序结构
主程序:
byte[] bytes = new Byte[1024];
IPAddress ipAddress = IPAddress.Parse("192.168.1.104");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// 生成一个TCP的socket
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
//开启异步监听socket
Console.WriteLine("Waiting for a connection");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// 让程序等待,直到连接任务完成。在AcceptCallback里的适当位置放置allDone.Set()语句.
allDone.WaitOne();
}
Console.WriteLine("\nPress ENTER to continue");
Console.Read();
连接行为回调函数AcceptCallback:
public static void AcceptCallback(IAsyncResult ar)
{
//添加此命令,让主线程继续.
allDone.Set(); // 获取客户请求的socket
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar); // 造一个容器,并用于接收命令.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
读取行为的回调函数ReadCallback:
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty; // 从异步state对象中获取state和socket对象.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket; // 从客户socket读取数据.
int bytesRead = handler.EndReceive(ar); if (bytesRead > 0)
{
// 如果接收到数据,则存起来
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); // 检查是否有结束标记,如果没有则继续读取
content = state.sb.ToString();
if (content.IndexOf("") > -1)
{
//所有数据读取完毕.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content);
// 给客户端响应.
Send(handler, content);
}
else
{
// 接收未完成,继续接收.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
发送消息给客户端:
private static void Send(Socket handler, String data)
{
// 消息格式转换.
byte[] byteData = Encoding.ASCII.GetBytes(data); // 开始发送数据给远程目标.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
} private static void SendCallback(IAsyncResult ar)
{
// 从state对象获取socket.
Socket handler = (Socket)ar.AsyncState; //完成数据发送
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent); handler.Shutdown(SocketShutdown.Both);
handler.Close(); }
在各种行为的回调函数中,所对应的socket都从输入参数的AsyncState属性获得。使用(Socket)或者(StateObject)进行强制转换。BeginReceive函数使用的容器为state,因为它需要存放传送的数据。
而其余接收或发送函数的容器为socket也可。
完整代码
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading; // State object for reading client data asynchronously
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
} public class AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false); public AsynchronousSocketListener()
{
} public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024]; // Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
//IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = IPAddress.Parse("192.168.1.104");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); // Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp); // Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(100); while (true)
{
// Set the event to nonsignaled state.
allDone.Reset(); // Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener); // Wait until a connection is made before continuing.
allDone.WaitOne();
} }
catch (Exception e)
{
Console.WriteLine(e.ToString());
} Console.WriteLine("\nPress ENTER to continue");
Console.Read(); } public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set(); // Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar); // Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
} public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty; // Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket; // Read data from the client socket.
int bytesRead = handler.EndReceive(ar); if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead)); // Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("") > -1)
{
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content);
// Echo the data back to the client.
Send(handler, content);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
} private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
} private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState; // Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent); handler.Shutdown(SocketShutdown.Both);
handler.Close(); }
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
} public static int Main(String[] args)
{
StartListening();
return 0;
}
}
(转)C# Socket异步通信的更多相关文章
- socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto
socket异步通信-如何设置成非阻塞模式.非阻塞模式下判断connect成功(失败).判断recv/recvfrom成功(失败).判断send/sendto 博客分类: Linux Socket s ...
- Socket异步通信学习三
接下来是客户端部分,采用同步接收模式,在SocketClient项目中新建了一个SynServer类,用于存放socket服务器代码,和AsynServer类似,主要有4个方法: 有一个全局socke ...
- Socket异步通信学习二
接下来是服务器部分,采用异步模式,新建了一个AsynServer类,用于存放socket服务器代码,主要有4个方法: 有一个全局socket,下面四个方法中都用到. Socket socket = n ...
- Socket异步通信学习一
最近在做一个频谱管理项目,负责通信模块,自己也是小白,重头学起,直至今天通信基本框架已经完成,把自己在学习中的心得与大家分享一下,做一个socket系列的博文,顺便加固一下自己对socket通信的认识 ...
- Socket异步通信及心跳包同时响应逻辑分析。
有段时间没有更博了,刚好最近在做Socket通信的项目,原理大致内容:[二维码-(加logo)]-->提供主机地址和端口号信息(直接使用[ThoughtWorks.QRCode.dll]比较简单 ...
- socket 异步通信的一些问题
socket通信在使用时被封装很简单,像操作文件一样简单,正是因为简单里面好多细节需要深入研究一下. windows下通信有select和iocp方式,select是传统方式,在socket里使用re ...
- Socket 异步通信
最近在写数据通信的时候用到的东西!希望对大家有帮助 /// <summary> /// 获取或设置服务器IP地址 /// </summary> public string se ...
- Socket异步通信及心跳包同时响应逻辑分析(最后附Demo)。
有段时间没有更博了,刚好最近在做Socket通信的项目,原理大致内容:[二维码-(加logo)]-->提供主机地址和端口号信息(直接使用[ThoughtWorks.QRCode.dll]比较简单 ...
- Socket 异步通信示例
这个项目是一个控制台应用程序: 服务器端: using System; using System.Net; using System.Net.Sockets; using System.Text; u ...
随机推荐
- 统计mysql数据库中数据表/字段等数量的sql
1.查询一个表中有多少个字段: SELECT COUNT(*) FROM information_schema. COLUMNSWHERE table_schema = '数据库名'AND table ...
- hdu 5777 domino 贪心
domino Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Problem ...
- org.apache.log4j.Logger用法
在应用程序中添加日志记录总的来说基于三个目的 :监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作:跟踪代码运行时轨迹,作为日后审计的依据:担当集成开发环境中的调试器的作用,向文 ...
- git branch 常用语句详解
删除远程分支 git push origin --delete <branchName> 查看本地分支 git branch 创建本地新分支 git branch <branchNa ...
- Ubuntu 16 安装redis客户端
https://snapcraft.io/redis-desktop-manager sudo snap install redis-desktop-manager 很好用! 支持模糊过滤,两边加星号 ...
- scala学习手记22 - 参数化类型的可变性
java 的代码中多少有些不是很严谨的内容,比如下面的这段代码: public class Trouble { public static void main(String[] args) { Int ...
- [Hadoop] - Hadoop 3.x版本新特性
仅做记录--->官方说明:http://hadoop.apache.org/docs/r3.0.0-alpha2/index.html ============================= ...
- HTML5标签学习
<abbr> 表示一个缩写形式,比如 "Inc."."etc.".通过对缩写词语进行标记,您就能够为浏览器.拼写检查程序.翻译系统以及搜索引擎分度器 ...
- leetcode 2SUM
; i < numbers.size(); ++i){ ; i < v.size(); i++){ ; j < v.size ...
- Codeforces Round #181 (Div. 2)C
用lucas定理, p必须是素数 对于单独的C(n, m) mod p,已知C(n, m) mod p = n!/(m!(n - m)!) mod p.显然除法取模,这里要用到m!(n-m)!的逆元. ...