Я устанавливаю связь через сокет, но у меня проблемы с отправкой данных с сервера. Я могу отправить ответ после получения чего-либо, но мне нужно иметь возможность отправить сообщение, не получая заранее ничего от клиента.

Я хочу просто отправить команду через сокет после того, как соединение будет установлено. (после вызова 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);
           ...
      }

Работаю над этой проблемой уже больше недели. Трудно сказать, что я пробовал раньше, потому что я чувствую, что перепробовал все и искал помощи в самых глубоких уголках Интернета. Так что я стою перед тем, что а) я где-то суперслепой, б) я перегружен работой или в) на самом деле невозможно, извини, Рино, тебе нужно отказаться от своего проекта и начать заново.

В любом случае буду благодарен за любую помощь. Спасибо.

0
Rhino 9 Фев 2021 в 14:10

1 ответ

Лучший ответ

Вот как я решил свои проблемы: Проблема заключалась в том, что я не использовал BeginSend (...) в соединении сокета, которое я использовал с EndAccept (), которое было просто названо 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);
           ...
      }
0
Rhino 19 Фев 2021 в 08:23