Search code examples
c#socketstcpserver

C# Socket: Server doesn't send messages


I'm making a communication via a socket but I'm having problems sending data from the server. I'm able to send a response after receiving something but I need to be able to send a message without receiving anything from the client beforehand.

What I want to do is basically send a command over the socket after a connection is established. (after AcceptCallback() was called, which I check for). In my main program I have a button which I want to be able to click anytime to send a certain message. However, every time I try this I get an error that I cannot anything over an unconnected socket.

As you can see in the code I tried to send another message after receiving something from my client (see in the ReceiveCallback() where I send "Test send"). Sending that works, but if I want to send something else afterwards it again gives the error that I can't send something over a disconnected socket.

The current code looks like this(excerpts):

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);
           ...
      }

I've been working on this problem for over a week now. It's kind of hard to say what I tried before because I feel like I've tried everything and looked in the deepest part of the internet for help. So I'm standing before that possibilities that a)I am super blind somewhere, b) I'm overworked or c) it's actually impossible, sorry Rhino you need to scrap your project and start anew.

Anyway I'd be grateful for any kind of help. Thanks.


Solution

  • This is how I solved my problems: The Problem was that I didn't use BeginSend(...) on the socket connection that I had used with EndAccept(), which was just named socket. To be able to use this specific socket in any other method and not just the AcceptCallback(), I had to make it accessible. I created a List to save Accepted sockets in called _clientSockets to which I added every accepted socket. It now looks like this (only the parts that changed):

    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);
               ...
          }