C# 套接字:服务器不发送消息

时间:2021-02-09 11:10:12

标签: c# sockets tcpserver

我正在通过套接字进行通信,但在从服务器发送数据时遇到问题。 我可以在收到某些信息后发送响应,但我需要能够发送消息而无需事先从客户端接收任何信息。

我想要做的基本上是在建立连接后通过套接字发送命令。 (在调用 AcceptCallback() 之后,我检查了它)。在我的主程序中,我有一个按钮,我希望能够随时单击该按钮以发送特定消息。但是,每次尝试此操作时,我都会收到一个错误,即我无法通过未连接的套接字执行任何操作。

正如您在代码中看到的,我在从我的客户端接收到一些东西后尝试发送另一条消息(参见 ReceiveCallback() 中我发送“测试发送”的地方)。发送有效,但如果我想在之后发送其他内容,它会再次给出错误,即我无法通过断开连接的套接字发送内容。

当前代码如下(摘录):

class SocketServer
{
 private static Socket _serverSocket;
//Konstruktor
      public SocketServer(int port = 9851)
      {
          _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //Socket Objekt
          lep = new IPEndPoint(IPAddress.Any, 9851);
      }
      private static void AcceptClient()
      {
          try
          {
              _serverSocket.Bind(lep); 
              _serverSocket.Listen(100);                 
              _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), _serverSocket); //auf Verbindungen warten weiter bei AcceptCallback Methode
          }
          catch 
          {
              ...
          }
      }

      private static void AcceptCallback(IAsyncResult AR)     //Connection accept callback
      {
          
          try
          {
              Socket socket = _serverSocket.EndAccept(AR); 

              socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket); 
              _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), _serverSocket); 
          }
          catch (ObjectDisposedException e)
          {
              ...
          }
      }
private static void ReceiveCallback(IAsyncResult AR)//Weiterführung Empfangen
      {
          Socket socket = (Socket)AR.AsyncState;

          try
          {
              received = socket.EndReceive(AR); //Speichere Anzahl empfangener Bytes
              ... //trimming and saving the received data in a string
              sending = "Test send";
              byte[] data = Encoding.UTF8.GetBytes(sending);  
              socket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), socket); 
          }
          catch (ObjectDisposedException e)
          {
              ...
          }
      }
public void SendMessage() 
      {
          byte[] data = Encoding.UTF8.GetBytes(sending);  
          _serverSocket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), _serverSocket); //Beginnen des Sendevorgangs weiter bei SendCallback
       ...
      }

      private static void SendCallback(IAsyncResult AR) 
      {
          Socket socket = (Socket)AR.AsyncState;
          socket.EndSend(AR);
           ...
      }

我已经研究这个问题一个多星期了。很难说我之前尝试过什么,因为我觉得我已经尝试了一切,并且在互联网的最深处寻求帮助。所以我站在这种可能性之前,a) 我在某个地方超级失明,b) 我工作过度或 c) 这实际上是不可能的,抱歉 Rhino,你需要放弃你的项目并重新开始。

无论如何,我会很感激任何形式的帮助。谢谢。

1 个答案:

答案 0 :(得分:0)

我是这样解决问题的: 问题是我没有在与 EndAccept() 一起使用的套接字连接上使用 BeginSend(...),它只是命名为 socket。 为了能够在任何其他方法中使用此特定套接字,而不仅仅是 AcceptCallback(),我必须使其可访问。 我创建了一个列表以将接受的套接字保存在名为 _clientSockets 中,我将每个接受的套接字添加到该列表中。 现在看起来像这样(只有改变的部分):

class SocketServer
{
 private static Socket _serverSocket;
private static List<Sockets> _clientSockets=new List<Socket>();

private static void AcceptClient()
      {
          try
          {
              _serverSocket.Bind(lep); 
              _serverSocket.Listen(100);                 
              _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), _serverSocket); //auf Verbindungen warten weiter bei AcceptCallback Methode
          }
          catch 
          {
              ...
          }
      }

      private static void AcceptCallback(IAsyncResult AR)     //Connection accept callback
      {
          
          try
          {
              Socket socket = _serverSocket.EndAccept(AR); 

              socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket); 
              _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), _serverSocket); 
              _clientSockets.Add(socket); //This is the important part where I add the completed socket connection to the list!

          }
          catch
          {
              ...
          }
      }

public void SendMessage(string sdata, int socketno) 
      {
          Socket socket = _clientSockets[socketno] //Here I give the socket from before, or whichever one I choose, to this method to proceed with
          byte[] data = Encoding.UTF8.GetBytes(sdata);  
          socket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), socket); //Beginnen des Sendevorgangs weiter bei SendCallback
       ...
      }

      private static void SendCallback(IAsyncResult AR) 
      {
          Socket socket = (Socket)AR.AsyncState;
          socket.EndSend(AR);
           ...
      }