C# Net内核中的异步服务器套接字-如何返回结果?
我需要通过TCP异步发送数据。它是字符串的集合C# Net内核中的异步服务器套接字-如何返回结果?,c#,asynchronous,.net-core,tcp,tcpclient,C#,Asynchronous,.net Core,Tcp,Tcpclient,我需要通过TCP异步发送数据。它是字符串的集合ICollection 我搜索并找到了一个好的(见下文)。该示例似乎位于.netframework下,但我假设它也适用于.netcore 我在做什么: 我将代码重新定位为非静态类 我想发送一组字符串ICollection。我知道我可以重写它来发送main方法中的字符串集合。没问题 我希望收到每封邮件的回复,并对其进行处理。当前响应静态存储在private static String response=String.Empty中。我不希望它是静态的
ICollection
我搜索并找到了一个好的(见下文)。该示例似乎位于.netframework
下,但我假设它也适用于.netcore
我在做什么:
ICollection
。我知道我可以重写它来发送main方法中的字符串集合。没问题
private static String response=String.Empty中代码>。我不希望它是静态的。我想要一个局部方法变量
private static void ReceiveCallback(IAsyncResult ar)
我认为将其更改为私有静态字符串ReceiveCallback(IAsyncResult ar)
不起作用。如果是,我如何从client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,new-AsyncCallback(ReceiveCallback),state)读取它代码>
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
// State object for receiving data from remote device.
public class StateObject {
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousClient {
// The port number for the remote device.
private const int port = 11000;
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false);
// The response from the remote device. <------ ### the response data that I want to access, non statically
private static String response = String.Empty;
private static void StartClient() {
// Connect to a remote device.
try {
// Establish the remote endpoint for the socket.
// The name of the
// remote device is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.GetHostEntry("host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket client = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect( remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Send test data to the remote device.
Send(client,"This is a test<EOF>");
sendDone.WaitOne();
// Receive the response from the remote device.
Receive(client);
receiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", response);
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private static void ConnectCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket client = (Socket) ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client) {
try {
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state); //<------ The receive callback is here, how do I return the result to the caller?
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback( IAsyncResult ar ) {
try {
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.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));
// Get the rest of the data.
client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
new AsyncCallback(ReceiveCallback), state);
} else {
// All the data has arrived; put it in response.
if (state.sb.Length > 1) {
response = state.sb.ToString(); //<--------- ### Where it is assigned, I want it returned
}
// Signal that all bytes have been received.
receiveDone.Set();
}
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, 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.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket client = (Socket) ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args) {
StartClient();
return 0;
}
}
使用系统;
Net系统;
使用System.Net.Sockets;
使用系统线程;
使用系统文本;
//用于从远程设备接收数据的状态对象。
公共类StateObject{
//客户端套接字。
公共套接字工作组=null;
//接收缓冲区的大小。
public const int BufferSize=256;
//接收缓冲区。
公共字节[]缓冲区=新字节[BufferSize];
//接收到的数据字符串。
公共StringBuilder sb=新StringBuilder();
}
公共类异步客户端{
//远程设备的端口号。
专用常量int端口=11000;
//ManualResetEvent实例信号完成。
专用静态手动重置事件已完成=
新手动重置事件(错误);
私有静态手动重置事件sendDone=
新手动重置事件(错误);
私有静态手动重置事件接收完成=
新手动重置事件(错误);
//来自远程设备的响应。1){
response=state.sb.ToString();//您可以创建一个类(非静态,我称之为AsynchronousClient),该类直接从Microsoft示例中实现套接字通信的所有逻辑。相关添加包括3个事件(更多信息):
1) ConnectionComplete,异步连接操作完成时激发
2) SendComplete,在成功发送数据(本例中为字符串)时激发
3) DataReceived,当有来自远程端点的传入数据时激发
基本上,该类公开了3个公共方法:AsyncConnect、AsyncSend和AsyncReceive。在3个私有回调上,会触发上面列表中的相应事件,并通知使用AsynchronousClient的类操作终止
public class AsynchronousClient
{
/// <summary>
/// The client's socket instance.
/// </summary>
private Socket _clientSocket;
/// <summary>
/// Define the signature of the handler of the ConnectionComplete event.
/// </summary>
public delegate void ConnectionCompleteEventDelegate(AsynchronousClient sender, Socket clientSocket);
/// <summary>
/// Define the signature of the handler of the SendComplete event.
/// </summary>
public delegate void SendCompleteEventDelegate(AsynchronousClient sender, Socket clientSocket);
/// <summary>
/// Define the signature of the handler of the DataReceived event.
/// </summary>
public delegate void DataReceivedEventDelegate(AsynchronousClient sender, Socket clientSocket, string data);
/// <summary>
/// ConnectionComplete event the client class can subscribe to.
/// </summary>
public event ConnectionCompleteEventDelegate ConnectionComplete;
/// <summary>
/// SendComplete event a class using an AsynchronousClient instance can subscribe to.
/// </summary>
public event SendCompleteEventDelegate SendComplete;
/// <summary>
/// DataReceived event a class using an AsynchronousClient instance can subscribe to.
/// </summary>
public event DataReceivedEventDelegate DataReceived;
/// <summary>
/// The remote endpoint the socket is going to communicate to.
/// </summary>
public IPEndPoint RemoteEndpoint { get; private set; }
/// <summary>
/// Class initializer.
/// </summary>
/// <param name="remoteEndpoint">The remote endpoint to connect to.</param>
public AsynchronousClient(IPEndPoint remoteEndpoint)
{
RemoteEndpoint = remoteEndpoint;
// Create a TCP/IP socket.
_clientSocket = new Socket(
RemoteEndpoint.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
}
/// <summary>
/// Asynchronous connection request.
/// </summary>
public void AsyncConnect()
{
try
{
// Initiate the connection procedure to the remote endpoint.
_clientSocket.BeginConnect(
RemoteEndpoint,
new AsyncCallback(AsyncConnectCallback), _clientSocket);
}
catch (Exception ex)
{
// TODO: manage exception.
throw;
}
}
/// <summary>
/// Called after the connection to the remote endpoint is established.
/// </summary>
private void AsyncConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
// If a client class is subscribed to the event, invoke the delegate.
if (!(ConnectionComplete is null))
ConnectionComplete.Invoke(this, client);
}
catch (Exception ex)
{
// TODO: manage exception.
throw;
}
}
/// <summary>
/// Asynchronously sends a string to the remote endpoint.
/// </summary>
public void AsyncSend(string data)
{
try
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
_clientSocket.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(AsyncSendCallback), _clientSocket);
}
catch(Exception ex)
{
// TODO: manage exception.
throw;
}
}
/// <summary>
/// Called after the send operation is complete.
/// </summary>
private void AsyncSendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
// If a client class is subscribed to the event, invoke the delegate.
if (!(SendComplete is null))
SendComplete(this, client);
}
catch (Exception ex)
{
// TODO: manage exception.
throw;
}
}
/// <summary>
/// Asynchronously waits for a response from the remote endpoint.
/// </summary>
public void AsyncReceive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(AsyncReceiveCallback), state);
}
catch (Exception ex)
{
// TODO: manage exception.
throw;
}
}
/// <summary>
/// Called after the receive operation is complete.
/// </summary>
private void AsyncReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.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));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(AsyncReceiveCallback), state);
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
var response = state.sb.ToString(); //<--------- ### Where it is assigned, I want it returned
// If a client class is subscribed to the event, invoke the delegate.
// Here the client class is notified, and the response is passed as parameter to the delegate.
if (!(DataReceived is null))
DataReceived.Invoke(this, client, response);
}
}
}
catch (Exception ex)
{
// TODO: manage exception.
throw;
}
}
}
公共类异步客户端
{
///
///客户端的套接字实例。
///
专用套接字_clientSocket;
///
///定义ConnectionComplete事件处理程序的签名。
///
公共委托void ConnectionCompleteEventDelegate(异步客户端发送方、套接字客户端套接字);
///
///定义SendComplete事件处理程序的签名。
///
公共委托void sendpleteeventdelegate(异步客户端发送方,套接字clientSocket);
///
///定义DataReceived事件处理程序的签名。
///
公共委托void DataReceivedEventDelegate(异步客户端发送方、套接字客户端套接字、字符串数据);
///
///客户端类可以订阅的ConnectionComplete事件。
///
公共事件连接完成甚至删除连接完成;
///
///SendComplete事件使用AsynchronousClient实例的类可以订阅的事件。
///
公共事件SendCompleteEventDelegate SendComplete;
///
///使用AsynchronousClient实例的类可以订阅的DataReceived事件。
///
公共事件DataReceivedEventDelegate DataReceived;
///
///套接字要与之通信的远程端点。
///
公共IPEndPoint远程端点{get;private set;}
///
///类初始值设定项。
///
///要连接到的远程终结点。
公共异步客户端(IPEndPoint remoteEndpoint)
{
RemoteEndpoint=RemoteEndpoint;
//创建TCP/IP套接字。
_clientSocket=新套接字(
RemoteEndpoint.AddressFamily,
SocketType.Stream,
原型(Tcp);
}
///
///异步连接请求。
///
公共void异步连接()
{
尝试
{
//启动到远程端点的连接过程。
_clientSocket.BeginConnect(
远程端点,
新的AsyncCallback(AsyncConnectCallback),\u clientSocket);
}
捕获(例外情况除外)
{
//TODO:管理异常。
投掷;
}
}
///
///在与远程端点的连接建立后调用。
///
专用void AsyncConnectCallback(IAsyncResult ar)
{
尝试
{
//从sta中检索套接字
private AsynchronousClient _asyncClient;
private void Form1_Load(object sender, EventArgs e)
{
// I'm testing on the loopback interface.
var remoteIp = IPAddress.Parse("127.0.0.1");
// Create a new remote endpoint.
var remoteEndpoint = new IPEndPoint(remoteIp, 11000);
// Create a new instance of the AsynchronousClient client,
// passing the remote endpoint as parameter.
_asyncClient = new AsynchronousClient(remoteEndpoint);
// Subscription to the ConnectionComplete event.
_asyncClient.ConnectionComplete += AsyncClient_ConnectionComplete;
// Subscription to the SendComplete event.
_asyncClient.SendComplete += AsyncClient_SendComplete;
// Subscription to the DataReceived event.
_asyncClient.DataReceived += AsyncClient_DataReceived;
}
/// <summary>
/// Handler of the DataReceived event.
/// </summary>
private void AsyncClient_DataReceived(AsynchronousClient sender, Socket clientSocket, string data)
{
// Here I manage the data received by the remote endpoint.
MessageBox.Show(string.Format("Data received: {0}", data));
}
/// <summary>
/// Handler of the SendComplete event.
/// </summary>
private void AsyncClient_SendComplete(AsynchronousClient sender, Socket clientSocket)
{
// Here I'm starting an async receive operation, as I expect the remote endpoint
// to send back some data.
_asyncClient.AsyncReceive(clientSocket);
}
/// <summary>
/// Handler of the ConnectionComplete event.
/// </summary>
private void AsyncClient_ConnectionComplete(AsynchronousClient sender, Socket clientSocket)
{
// Here I just want to warn the user the connection is set.
MessageBox.Show("Successfully connected to the remote endpoint.");
}
/// <summary>
/// Handler of the connect button.
/// </summary>
private void BtnConnect_Click(object sender, EventArgs e)
{
_asyncClient.AsyncConnect();
}
/// <summary>
/// Handler of the SendString button.
/// </summary>
private void BtnSendString_Click(object sender, EventArgs e)
{
_asyncClient.AsyncSend("TEST DATA<EOF>");
}
ICollection<string> strings = ...;
using Socket socket = ...;
using var stream = new NetworkStream(socket);
using var writer = new StreamWriter(stream);
foreach(string s in strings)
{
await writer.WriteLineAsync(s);
}
await writer.FlushAsync();