[英]Handling sockets using internal classes in C#
I have created a class that acts as a plugin for another application. 我创建了一个充当另一个应用程序插件的类。 It should hold functions to use in the main application.
它应该拥有要在主应用程序中使用的功能。 It works in general - that means i can handle usual functions like calculations and even reading files.
它通常可以正常工作-这意味着我可以处理常用功能,例如计算甚至读取文件。 But i have problems implementing a socket class.
但是我在实现套接字类时遇到问题。 I know how to work with sockets in general but in this case i have a problem.
我知道一般如何使用套接字,但是在这种情况下我有问题。
As you may see in the code, there is an internal class SockAttrib
that should manage the socket creation, the listening and also the messages. 您可能会在代码中看到,有一个内部类
SockAttrib
应该管理套接字的创建,侦听以及消息。 Received messages are stored in a dictionary. 收到的消息存储在字典中。
public class Net : Module {
private static ReadOnlyCollection<CustomMethod> customMethods;
internal class SockAttrib {
public Socket listener;
public Socket handler;
/* create the listener */
public SockAttrib(int port) {
IPHostEntry host = Dns.GetHostEntry("localhost");
IPAddress ipAddress = host.AddressList[1];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
try {
listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(10);
handler = listener.Accept();
} catch (Exception e) { Console.WriteLine("socket() " + e); }
}
/* listen */
public SockAttrib() {
try {
// Incoming data from the client.
string data = "";
byte[] bytes = null;
while (true) {
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>") > -1)
{
messages[++idm] = data;
//return;
}
}
}
catch (Exception e) { Console.WriteLine("listen() "+e); }
}
public void Close() {
handler.Close();
}
}
/* message index */
private static int idm = 0;
/* list of messages */
private static Dictionary<int, String> messages = new Dictionary<int, String>();
public Net() {
if (customMethods != null) return;
List<CustomMethod> moduleMethods = new List<CustomMethod>();
moduleMethods.Add(new CustomMethod(typeof(int), "socket", typeof(int)));
moduleMethods.Add(new CustomMethod(typeof(int), "listen" ));
moduleMethods.Add(new CustomMethod(typeof(string), "sockread"));
customMethods = moduleMethods.AsReadOnly();
}
public ReadOnlyCollection<CustomMethod> Prototypes {
get { return customMethods; }
}
public object OnMethodInvoke(String functionName, List<object> parameters) {
if( functionName == "socket") {
int port = (int)parameters[0];
SockAttrib sa = new SockAttrib( port );
return 1;
}
if (functionName == "listen") {
SockAttrib sa = new SockAttrib();
return 1;
}
if (functionName == "sockread") {
if (idm > 0) {
String message = messages[--idm];
return message;
} else {
return "nope";
}
}
return false;
}
}
My problem is the handler. 我的问题是处理程序。 The creation of the socket works but as soon as i connect to the socket using netcat the socket stop listening and i dont get any responses.
套接字的创建工作正常,但是一旦我使用netcat连接到套接字,套接字就会停止监听,并且我没有任何响应。 I hope its not too much code and it should also be easy readable.
我希望它的代码不要太多,并且也应该易于阅读。
Finally the module gets exported as a library (dll) so i cant really give a minimal working example without also posting the module handler. 最终,模块被导出为库(dll),因此我不能在不发布模块处理程序的情况下给出一个最小的工作示例。
Though your requirements are still a bit fuzzy, I will give it a try. 尽管您的要求仍然有些模糊,但我会尝试一下。
First I would recommend to create a class containing the core functionality of your TCP server. 首先,我建议创建一个包含TCP服务器核心功能的类。 This makes it easier to unit-test your code and to adapt it to changing requirements.
这使对代码进行单元测试并使之适应不断变化的需求变得更加容易。
/// <summary>
/// This class encapsulates the TCP server
/// </summary>
public class Server : IDisposable
{
private static TcpListener _listener;
private static TcpClient _client;
private static NetworkStream _stream;
private static byte[] _buffer;
private static readonly StringBuilder _receivedText = new StringBuilder();
private const string EOF = "<EOF>";
/// <summary>
/// Starts listening on the specified port
/// </summary>
/// <param name="port">The port number</param>
public Server(int port)
{
_listener = new TcpListener(IPAddress.Any, port);
_listener.Start();
_listener.BeginAcceptTcpClient(Accepted, null);
}
public void Dispose()
{
if (_client != null)
{
_client.Dispose();
}
if (_listener != null)
{
_listener.Stop();
}
}
/// <summary>
/// Returns any text that has been sent via TCP to the port specified in the constructor.
/// </summary>
/// <returns>The received text, or null if no (complete) text has been received yet.</returns>
/// <remarks>
/// The method returns the next text delimited by "<EOF>".
/// </remarks>
public string Read()
{
lock (_receivedText)
{
var receivedText = _receivedText.ToString();
var eofIndex = receivedText.IndexOf(EOF);
if (eofIndex < 0)
return null; // no (complete) text has been received yet
var result = receivedText.Substring(0, eofIndex);
_receivedText.Remove(0, eofIndex + EOF.Length);
return result;
}
}
// called whenever a client has connected to our server.
private static void Accepted(IAsyncResult ar)
{
_client = _listener.EndAcceptTcpClient(ar);
_stream = _client.GetStream();
_buffer = new byte[4096];
_stream.BeginRead(_buffer, 0, _buffer.Length, Read, null);
}
// called whenever data has arrived or if the client closed the TCP connection
private static void Read(IAsyncResult ar)
{
var bytesReceived = _stream.EndRead(ar);
if (bytesReceived == 0)
{
// TCP connection closed
_client.Close();
_client = null;
_stream.Dispose();
_stream = null;
// prepare for accepting the next TCP connection
_listener.BeginAcceptTcpClient(Accepted, null);
return;
}
lock (_receivedText)
{
_receivedText.Append(Encoding.ASCII.GetString(_buffer, 0, bytesReceived));
}
// prepare for reading more
_stream.BeginRead(_buffer, 0, _buffer.Length, Read, null);
}
}
Integrating this into your Net
class should then be fairly simple: 然后将其集成到您的
Net
类中应该非常简单:
// static or not? Depends on your "Module plugin" architecture
private static Server _server;
public object OnMethodInvoke(String functionName, List<object> parameters)
{
if (functionName == "socket")
{
if (_server != null)
{
// oops, already open
return 0;
}
int port = (int)parameters[0];
_server = new Server(port);
return 1;
}
if (functionName == "sockread")
{
if (_server != null)
{
return _server.Read() ?? "nope";
}
else
{
return "nope";
}
}
return false;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.