c# - C# 通过套接字发送字节数组
问题描述
我一直在尝试将字节数组从客户端发送到服务器以构建身份验证服务器。
我已经使用 Microsoft 异步服务器套接字示例成功发送了字节数组。链接 但是在他们的示例中,他们使用字符串来指示字节传输的结束。
content.IndexOf("<EOF>") > -1
我不喜欢这种方法并将其删除,因此服务器一直等待来自客户端的消息,直到客户端或服务器数据包处理程序决定关闭套接字。
我不明白需要一个字符串来指示 transfer 的结束。我可以通过数组长度检查这个吗? 我使用的方法是否足够安全以确保数据完整性?
我的代码服务器端:在方法中进行了更改:ReadCallback
public class AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public AsynchronousSocketListener()
{
}
public static void StartListening(String hostname, int port)
{
// Establish the local endpoint for the socket.
// The DNS name of the computer
// example running the listener is "localhost".
IPHostEntry ipHostInfo = Dns.GetHostEntry(hostname);
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket listener = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
try
{
// Bind the socket to the local endpoint and listen for incoming connections.
listener.Bind(localEndPoint);
listener.Listen(100);
// Do not stop after one connection
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Listening for new connection");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before listening again
// for a new connection.
allDone.WaitOne();
Console.WriteLine("Connection established.");
}
}
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);
// New way, handles forcibly disconnect.
SocketError errorCode;
int bytesRead = 0;
try
{
bytesRead = handler.EndReceive(ar, out errorCode);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
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));
PacketHandler.CheckPacket(
handler: handler,
data: state.buffer,
length: bytesRead
);
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content);
// Keep listening to the socket for messages while the socket is connected.
if (handler.Connected)
{
// Empty the previous message
state.sb.Clear();
try
{
// Recursieve? Calling itself til socket is disposed off.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Thread.Sleep(1000);
}
// If it got this far, means socket is closed. Double checking before disposing of the socket.
if (!handler.Connected)
{
try
{
// https://stackoverflow.com/questions/4160347/close-vs-shutdown-socket
handler.Shutdown(SocketShutdown.Both);
handler.Close();
Console.WriteLine("Closed socket");
}
catch (Exception ex)
{
Console.WriteLine("Failed close socket. " + ex.Message);
}
}
//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);
}
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());
}
}
}
解决方案
推荐阅读
- angular - Angular Material Reactive 表单单选按钮组不起作用
- python - Pandas:结合实际值和预测值
- snakemake - Snakemake 在规则中使用相同的输入和输出
- python - 使用多文件夹和文件和 TensorFlow 部署 exe Kivy
- mysql - 带有 MySQL 和 Maria DB 提交和回滚问题的 Spring Boot JDBCTemplate
- java - 如何确保 Java Web Start 应用程序的单个实例正在客户端计算机上运行?
- javascript - 递归 axios 调用
- python - pandas:在组内使用条件进行迭代
- c# - 如何在 ASP.NET Core 重写模块中使用 {PATH_INFO}?
- android - Angular/Cordova 应用程序 html5 视频标签无法在 Android 上播放