c# - 在 C# 中使用异步套接字发送字节数组时遇到问题?
问题描述
我一直在关注 Microsoft 提供的关于如何实现异步服务器套接字的 .NET 教程之一。我的目标是在 Microsoft 给定的代码中实现一个名为 writeToClient(byte[] input) 的新函数。
此函数将由位于不同应用程序中的另一个函数执行,并且在被调用时,它将接收一个字节数组作为输入,并通过在 Raspberry Pi 上运行的套接字将其转发到另一个应用程序,理想情况下使用 Send()。
到目前为止,我面临的主要问题是 Send(Socket handler, string data) 函数需要两个参数。为此,我一直无法找到一种方法可以将这两个应用程序合并为一个并实现我的目标。
有什么想法吗?
谢谢,
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
// State object for reading client data asynchronously
namespace UDCManager
{
public class StateObject
{
// 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();
// Client socket.
public Socket workSocket = null;
}
public class AsynchronousServerSocket
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public static void StartListening()
{
IPAddress IP = IPAddress.Any;
IPEndPoint EP = new IPEndPoint(IP, 24000);
Socket listner = new Socket(IP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listner.Bind(EP);
listner.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...");
listner.BeginAccept(
new AsyncCallback(AcceptCallback),
listner);
// 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("<EOF>") > -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);
}
}
}
public 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);
}
**public static void writeToClient(byte[] input)
{
}**
public 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());
}
}
}
}
解决方案
如果我正确理解了这个问题,你会想要这样的东西
// Expose a socket as a private variable, for example
private static Socket _socket;
public static void StartListening()
{
IPAddress IP = IPAddress.Any;
IPEndPoint EP = new IPEndPoint(IP, 24000);
_socket = new Socket(IP.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // <<<< HERE
// ...
}
// then you could use it in the write method
public static void writeToClient(byte[] input)
{
// validate input for null, and size
// validate that _socket has been created (optionally)
_socket.BeginSend(input, 0, input.Length, 0,
new AsyncCallback(SendCallback), handler)
}
如果您可以从同步代码开始可能会更简单,然后在工作之后,使用 async/await 将其转换为新样式的异步代码
推荐阅读
- ruby-on-rails - ActiveRecord::Delegation 模块中的@klass 是什么?
- javascript - 如何从 Android 中的 JavaScript 获取真/假?
- r - 如何在基于 rstudio ubuntu 上轻松切换 R 版本?
- postgresql - 无法启用 pgsql 远程连接
- android - 错误:程序类型已存在:android.support.v4.app.INotificationSideChannel
- karate - 调用数组或 csv 的每个值作为 url 中的参数
- python-2.7 - 在烧瓶中拆分文件时得到 404
- javascript - 为什么这个 Javascript Initial Cap 函数不起作用?
- streaming - 如何实际下载/传输使用 UPnP 找到的文件?
- node-ffi - 使用 node-ffi 读取字符指针数据时的空缓冲区