Problem z nową formą

0

Witam. Jestem w trakcie pisania komunikatora internetowego. Aktualnie próbuję rozwiązać problem związany z prywatnymi wiadomościami (tzn. ktoś klika dwa razy na kontakt, otwiera się nowa forma, następnie wysyła wiadomość przez poprzez przycisk wyślij i u odbiorcy po otrzymaniu wiadomości otwiera się forma z tą wiadomością). Okno u odbiorcy otwiera się ale od razu zawiesza i nie widać nic co zostało (jeżeli w ogóle zostało) otrzymane. Z góry dziękuje za jakąkolwiek pomoc. Poniżej 4 procedury (nasłuchu klientów, połączenia do klienta (przez double click na liście kontaktów), i klasa z obsługą odbierania i wysyłania:

NASŁUCH:

private void nasluchuj_klientow()
        {
            IPEndPoint lokalne = new IPEndPoint(IPAddress.Any, 2001);
            klient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Socket accepted = null;

            try
            {
                klient.Bind(lokalne);
                klient.Listen(100);

                while (true)
                {
                    accepted = klient.Accept();

                    if (accepted.Connected)
                    {
                        wiadomosci = new Private(accepted );
                        AddItem("NASŁUCHANO KLIENTA");
                    }

                }
            }
            catch (SocketException ex)
            {
                //MessageBox.Show("Wystąpił błąd " + ex);
            }
        }

POŁĄCZENIE:

private void podlacz_do(string ip)
        {
            s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint kontakt = new IPEndPoint(IPAddress.Parse(ip), 2001);

            try
            {
                s.Connect(kontakt);
                if (s.Connected)
                {
                    wiadomosci = new Private(s);
                    wiadomosci.Show();
                    AddItem("PODŁĄCZONO DO KIENTA");
                }        
            }
            catch(SocketException ex)
            {
                //MessageBox.Show("Wystąpił błąd " + ex);
            }
        } 

KLASA PRIVATE:

...
public Private(Socket s)
        {
            InitializeComponent();
            odbiorca = s;
            Thread.Sleep(100);

            odbieranie = new Thread(new ThreadStart(delegate { otrzymane(s); }));
            odbieranie.IsBackground = true;
            odbieranie.Start();
        }

        public void AddItem(string element)
        {
            if (this.listBox1.InvokeRequired)
            {
                AddItemCallback d = new AddItemCallback(AddItem);
                this.Invoke(d, new object[] { element });
            }
            else
            {
                listBox1.Items.Add(element);
            }
        }

        public void ShowMe()
        {
            if (this.InvokeRequired)
            {
                ShowMeCallBack d = new ShowMeCallBack(ShowMe);
                this.Invoke(d, new object[] { });
            }
            else
            {
                this.Show();
            }
        }

       private void wyslane(Socket odbiorca, string tekst)
        {
            try
            {
                if (tekst != "")
                {
                    byte[] buffor = Encoding.UTF8.GetBytes(tekst);
                    odbiorca.Send(buffor);
                    tekst = "";
                }
            }
            catch (SocketException ex)
            {
                AddItem("Wystąpił błąd: " + ex);
            }
            catch (ObjectDisposedException ex)
            {
                AddItem("Nie można połączyć z serwerem");
            }
        }

        private void otrzymane(Socket nadawca)
        {
            byte[] msg = new byte[4000];
            //string wiadomosc = "";

            try
            {
                while (true)
                {
                    nadawca.Receive(msg);
                    string wiadomosc = Encoding.ASCII.GetString(msg);

                    if (wiadomosc != "")
                    {
                        this.Show();
                        this.AddItem(wiadomosc);
                    }
                    wiadomosc = "";

                    wysylanie = new Thread(new ThreadStart(delegate { wyslane(nadawca, wiadomosc); }));
                    wysylanie.IsBackground = true;
                    wysylanie.Start();
                }
            }
            catch (SocketException ex)
            {
                //AddItem("Wystąpił błąd: " + ex);
            }
        }
...
1

dodam coś od siebie, polecam poczytanie o asynchronicznych socketach
http://www.codeproject.com/KB/IP/ChatAsynchTCPSockets.aspx
http://www.codeguru.com/csharp/csharp/cs_network/sockets/article.php/c7695

A dlaczego w wysyłaniu masz kodowanie **UTF8 **a w odbieraniu ASCII??? O_o

0
maszynaz napisał(a)

dodam coś od siebie, polecam poczytanie o asynchronicznych socketach
http://www.codeproject.com/KB/IP/ChatAsynchTCPSockets.aspx
http://www.codeguru.com/csharp/csharp/cs_network/sockets/article.php/c7695

A dlaczego w wysyłaniu masz kodowanie **UTF8 **a w odbieraniu ASCII???

Kodowanie poprawiłem, ale oczywiście nie zmieniło to za bardzo działania programu. Co do samej obsługi asynchronicznej socketów to się naczytałem. Zresztą komunikator działa w oparciu o serwer (ale na jednej formie, właśnie tak jak jest w poradnikach/tutorialach). Teraz chcę zrobić komunikację p2p z wyskakującym okienkiem prywatnej rozmowy. Klient łączy się do klienta, ale okno odbioru się zwiesza...

0

poza tym odwoływanie się do GUI (1) w pętli powinno być w wątku i z zastosowaniem InvokeRequired

while (true)
{
     nadawca.Receive(msg);
     string wiadomosc = Encoding.ASCII.GetString(msg);
 
     if (wiadomosc != "")
    {
       this.Show(); //(1)
        this.AddItem(wiadomosc);//to nie wiem co to robi, jeśli to odnosi się do GUI to też ma być w wątku
    }
    ...
}
0
maszynaz napisał(a)

poza tym odwoływanie się do GUI (1) w pętli powinno być w wątku i z zastosowaniem InvokeRequired

while (true)
{
     nadawca.Receive(msg);
     string wiadomosc = Encoding.ASCII.GetString(msg);
 
     if (wiadomosc != "")
    {
       this.Show(); //(1)
        this.AddItem(wiadomosc);//to nie wiem co to robi, jeśli to odnosi się do GUI to też ma być w wątku
    }
    ...
}

W jeszcze jednym wątku? Teraz jest tak... w oknie głównym leci nasłuchiwanie (w wątku) jeżeli zaakceptowany zostanie klient to uruchamia się wątek z odbiorem wiadomości, który z kolei uruchamia wątek od wysyłania. Do tego jeszcze wstawić wątek do dodawania przesłanej treści? AddItem to właśnie procedura dodawania z invokiem (jest w pierwszym poście w klasie Private). Show faktycznie nie było z invokiem, ale jak dodałem to i tak dalej się blokuje okno przychodzącej wiadomości.

0
 public void AddItem(string element)
        {
            if (this.listBox1.InvokeRequired)
            {
                AddItemCallback d = new AddItemCallback(AddItem);
                this.Invoke(d, new object[] { element });// źle
                 this.listBox1.Invoke(d, new object[] { element });//dobrze
            }
            else
            {
                listBox1.Items.Add(element);
            }
        }
0

Dziękuję, ale niestety niczego to nie zmieniło :(

0

Prosiłbym Ciebie, żebyś wyśledził dokładnie(choć prawie dokładnie) w którym momencie się zawiesza program. Niestety nie mam możliwości jego przetestowania.

0

trudno coś wywnioskować przy problemach z wątkami, gdy nie ma kompletnego kodu i nie można nic uruchomić…

0

W klasie Form1 na samym dole są procedury nasłuchu i łączenia do klienta (nasłuch wywołany jest w wątku po akceptacji połączenia z serwerem - procedura połącz), klasa Private to okienko rozmowy prywatnej. Wciąż walcze, kombinuje i nic... Będę wdzięczny za jakiekolwiek wskazówki
<<<<< tu był link >>>>> <-- już nie potrzebne, bo problem rozwiązany

0
while (true)
                {
                    accepted = klient.Accept();
 
                    if (accepted.Connected)
                    {
                        wiadomosci = new Private(accepted );
                        AddItem("NASŁUCHANO KLIENTA");
                    }
 
                }

Nasłuchiwanie (to powyżej) powinno być w wątku.

0
maszynaz napisał(a)

...
Nasłuchiwanie (to powyżej) powinno być w wątku.

Lokos napisał(a)

...(nasłuch wywołany jest w wątku po akceptacji połączenia z serwerem - procedura połącz) ...

Połączenie jest ok, bo się łączy, tylko odbiór albo wysyłka się zawiesza. Pewnie coś z tą klasą Private jest nie tak...

0

zakomentuj

 this.Show();
 this.AddItem(wiadomosc);

i zobacz czy nadal ci blokuje formę

0

Po zakomentowaniu nie blokuje się nic, ale też nie pojawia się okno odbioru wiadomości.
Na pewno show blokuje, ale gdzie go indziej wstawić wtedy?

0
 private void otrzymane(Socket nadawca)
        {
           ...
                    if (wiadomosc != "")
                    {
                        this.Show();//źle
                        this.ShowMe(); //dobrze
                        this.AddItem(wiadomosc);
                    }
          ....
        }
0

Poprawiłem to już wcześniej, jak pisałeś o invoke'ach ale to nic nie zmieniło.

1 użytkowników online, w tym zalogowanych: 0, gości: 1