none
TcpClient disconnects after write.

    Question

  • Tengo 2 aplicacciones, un cliente y un servidor. Al servidor se pueden conectar varios clientes. Cada ~20 segundos el servidor envia un byte a cada cliente y el cliente le devuelve la peticion enviandole otro byte para verificar cuales de los clientes siguen conectados. 

    Cuando un cliente envia un mensaje al servidor el servidor lo envia al resto de clientes. El problema es que cuando el cliente envia el primer mensaje se cierra y no consigo enviar mas.

     

    El servidor me devuelve la siguente excepcion Operación no permitida en sockets no conectados.

    Server

     

     class uServer
     {
     TcpListener ServerS;
     Thread MainTh;
     public bool stop = false;
     int id = 1;
     int aux = 0;
     List<Client> clients = new List<Client>();
     Logfile log;
     public uServer(string logFile)
     {
      ServerS = new TcpListener(new IPEndPoint(IPAddress.Any, 2145));
      log = new Logfile(logFile);
     }
     private void CheckOnline()
     {
      for (int x = 0; x < clients.Count; x++)
      {
      if (!clients[x].Connected)
      {
       clients[x].client.Close();
       clients.Remove(clients[x]);
      }
      } 
     }
     public List<Hashtable> GetClients()
     {
      List<Hashtable> lst = new List<Hashtable>();
      for (int x = 0; x < clients.Count; x++)
      lst.Add(clients[x].info);
      return lst;
     }
     private void ParseRequests()
     {
     for (int x = 0; x < clients.Count; x++)
     {
      if (clients[x].Available > 0)
      {
       byte[] b = new byte[clients[x].Available];
      //ERROR SIGUIENTE LINEA
      NetworkStream str = clients[x].client.GetStream();
      str.Read(b, 0, b.Length);
      SendMessageToAll(clients[x], Encoding.Default.GetString(b));
      b = null;
      }
      }
     }
     private void SendMessageToAll(Client from, string message)
     {
     for (int x = 0; x < clients.Count; x++)
     if (clients[x] != from)
      clients[x].SendMessage(from.info["Name"].ToString() + ":" + message);
     }
     private void Listen()
     {
      ServerS.Start(200);
      while (!stop)
      {
      if (ServerS.Pending())
      {
       TcpClient cl = ServerS.AcceptTcpClient();
       try
       {
        Client c = new Client(cl, id++);
        clients.Add(c);
        log.Write("Client connected from -> " + c.client.Client.RemoteEndPoint.ToString() + log.endl);
       }
       catch { cl.Close(); }
      }
      if (++aux % 200 == 0)
      {
       CheckOnline();
       aux = 0;
      }
      ParseRequests();
      Thread.Sleep(100);
      }
      ServerS.Stop();
      MainTh.Abort();
     }
     public void StartListening()
     {
     MainTh = new Thread(new ThreadStart(Listen));
     MainTh.Start();
     }
     internal class Client
     {
     public TcpClient client;
     public Hashtable info = new Hashtable();
     private NetworkStream str;
     public Client(TcpClient client, int id)
     {
     this.client = client;
     if (client.Available < 1)
     {
     throw new InvalidOperationException();
     }
     info.Add("id", id);
     str = client.GetStream();
     string s = "";
     while (client.Available > 0)
     s += ((char)str.ReadByte()).ToString();
     string[] information = s.Split(';');
     for (int x = 0; x < information.Length; x++)
     {
     string[] aux = information[x].Split(':');
     info.Add(aux[0], aux[1]);
     }
     client.ReceiveTimeout = 2000;
     client.SendTimeout = 2000;
    
     }
     public int ID
     {
     get { return (int)info["id"]; }
     set { info["id"] = value; }
     }
     public bool Connected
     {
     get
     {
     bool a = true;
     if (client == null)
     a = false;
     try
     {
     str.WriteByte((byte)1);
     byte b = (byte)str.ReadByte();
     if (b != 1)
     a = false;
     }
     catch
     {
     a = false;
     }
     return a;
     }
     }
     public int Available
     {
     get { return client.Available; }
     }
     public bool SendMessage(string msg)
     {
     if (msg.Length <= 0)
     return false;
     try
     {
     str.Write(Encoding.ASCII.GetBytes(msg), 0, Encoding.ASCII.GetBytes(msg).Length);
     byte b = (byte)str.ReadByte();
     if (b != 1)
     return false;
     }
     catch
     {
     return false;
     }
     return true;
    
     }
     }
     }
    

     

    Client

     

     private void button1_Click(object sender, EventArgs e)
     {
     //str is the network stream declared global
     str.Write(Encoding.Default.GetBytes(txtMessage.Text), 0, Encoding.Default.GetByteCount(txtMessage.Text));
     UpdateMessages(txtName.Text+":"+txtMessage.Text);
     }
     private void Read() {
     while (true) {
     if (client.Available > 0) {
     if (client.Available == 1)
     {
     byte b = (byte)str.ReadByte();
     if (b == 1)
     {
     str.WriteByte(1);
     UpdateMessages("Check if alive\n");
     }
     else
     UpdateMessages(((char)b).ToString() + "\n");
     }
     else {
     byte[] b = new byte[client.Available];
     str.Read(b, 0, b.Length);
     UpdateMessages(Encoding.Default.GetString(b) + "\n");
     }
     }
     Thread.Sleep(300);
     }
     }
    

     

    Thursday, July 08, 2010 11:08 AM

Answers

  • Ya encontre el fallo, en la clase interna Client hay una funccion que es send message. El problema era que despues de enviar el mensaje al cliente el servidor esperaba un byte como respuesta, pero desde el cliente no enviaba ninguna respuesta.

     

    public bool SendMessage(string msg)
     {
     if (msg.Length <= 0)
     return false;
     try
     {
     str.Write(Encoding.ASCII.GetBytes(msg), 0, Encoding.ASCII.GetBytes(msg).Length);
    //AQUI
     byte b = (byte)str.ReadByte();
     if (b != 1)
     return false;
     }
     catch
     {
     return false;
     }
     return true;
    
     }
    

    Friday, July 09, 2010 8:51 AM

All replies

  • eso es porque cada vez que revisas la conexión cierras la conexión:

     private void CheckOnline()
     {
     for (int x = 0; x < clients.Count; x++)
     {
     if (!clients[x].Connected)
     {
      //OJO ACA
      clients[x].client.Close();
      clients.Remove(clients[x]);
     }


    Juan Carlos Ruiz
    Microsoft MVP - Visual C#
    Visita mi blog:

    Ideas de Un Conejo - http://juank.black-byte.com

    Thursday, July 08, 2010 4:22 PM
  • Te equivocas, cada vez que veo algun cliente que no esta conectado, lo desconecto, pero lo que pasa es que el fallo no esta ahi. Aver si me explico cadavez que el servidor verifica sus conexiones si los clientes escriben en un RichTextBox que el servidor verifico si estaban conectados. Esta parte funcciona bien, por que lo deje verificar unos 2-3 minutos y ninguna de las conexiones se desconecto. Pero cuando envio desde un mensaje desde un cliente al servidor(desde un textBox) la conexion se cierra.
    Thursday, July 08, 2010 5:04 PM
  • ya entiendo, y si le haces debug al proceso exactamente en que linea te salta el error? y sobre todo cual es el stack de las excepcion?
    Juan Carlos Ruiz
    Microsoft MVP - Visual C#
    Visita mi blog:

    Ideas de Un Conejo - http://juank.black-byte.com

    Thursday, July 08, 2010 5:44 PM
  • Me dice que tiene pendiente informacion que recibir, pero cuando miro el estado del cliente me pone:

    [Socket].Connected false

    Thursday, July 08, 2010 7:11 PM
  • en que linea te salta el error? y sobre todo cual es el stack de la excepcion?


    Juan Carlos Ruiz - Microsoft MVP Visual C#
    Sígueme en Twitter:

    @JuanKRuiz

    Visita mi blog:

    C#, Videojuegos, Win32 - http://juank.black-byte.com

    Thursday, July 08, 2010 7:17 PM
  • Ya encontre el fallo, en la clase interna Client hay una funccion que es send message. El problema era que despues de enviar el mensaje al cliente el servidor esperaba un byte como respuesta, pero desde el cliente no enviaba ninguna respuesta.

     

    public bool SendMessage(string msg)
     {
     if (msg.Length <= 0)
     return false;
     try
     {
     str.Write(Encoding.ASCII.GetBytes(msg), 0, Encoding.ASCII.GetBytes(msg).Length);
    //AQUI
     byte b = (byte)str.ReadByte();
     if (b != 1)
     return false;
     }
     catch
     {
     return false;
     }
     return true;
    
     }
    

    Friday, July 09, 2010 8:51 AM