C#, sockety- gdzie umieścić kod odpowiedzialny za odbieranie

0

Witam,
Mam do napisania klienta SMTP,w C# kiedyś się tylko "bawiłem", poznałem podstawy, teraz poczytałem trochę o socketach w C# i pomyślałem, że dam radę.
Problem mam taki:
Aplikację mam okienkową (parę textboxów i buttony) i po połączeniu odbieram wiadomość od serwera, lecz gdy później coś wysyłam i oczekuję odpowiedzi program zawiesza się i jedynym wyjściem jest zamknięcie procesu. Być może ma to związek z moim pytaniem, które brzmi: gdzie umieścić kod odpowiedzialny za odbieranie wiadomości od serwera? Teraz mam w evencie buttona, po którego naciśnięciu wysyłam (czyli na jednym buttonie mam wysyłanie, a po tym odbieranie).
Pozdrawiam.

Poprawiłem temat, ale cały się nie zmieścił...

0
hck napisał(a)

gdzie umieścić kod odpowiedzialny za odbieranie wiadomości od serwera?

W oddzielnym watku.

hck napisał(a)

[...]a po tym odbieranie

Blokujesz glowny watek programu i dlatego wydaje sie ze program wisi.

0

Teraz pojawił się problem z wątkami.
Na MSDN jest taki przykład:

...
Thread newThread = new Thread(Work.DoWork);
newThread.Start(42);
...
public static void DoWork(object data)
    {
        Console.WriteLine("Static thread procedure. Data='{0}'",
            data);
    }

U mnie wygląda to tak:

...
Thread th = new Thread(new ParameterizedThreadStart(forma.ThreadOdbierz)); // przy tej lini blad
th.Start(clientSocket);
...
public string ThreadOdbierz(Socket so)
    {
        if (so.Connected)
        {
            byte[] rmsg = new byte[1024];
            int bajty;
            so.ReceiveTimeout = 3000;
            bajty = so.Receive(rmsg, 0, 1024, SocketFlags.None);
            do
            {
                textBox2.AppendText(Encoding.UTF8.GetString(rmsg));
                MessageBox.Show("Odebrano " + bajty.ToString());
                return Encoding.UTF8.GetString(rmsg);
            } while (bajty > 0);
        }
        Thread.Sleep(0);
        return "Błąd";
    }
...

Lecz podczas kompilacji dostaję błąd No overload for 'ThreadOdbierz' matches delegate 'System.Threading.ThreadStart'
Wcześniej miałem zamiast ParameterizedThreadStart ThreadStart i błąd był ten sam. Googlowanie powiedziało tylko, że trzeba zamienić na ParameterizedThreadStart.

0

Aha, no tak ThreadOdbierz musi brać object jako argument. Ale jak później zrobić z tego socket?

0

W zasadzie to nie muszę brać argumentów i z tego co widzę ta funkcja nie może nic zwracać ;/
Już prawie wszystko działa :)
Dziękuję i pozdrawiam.

0

A napisz sobie do tego klasę i trzymaj wszystko w jednym miejscu. Nie będzie problemu z parametrami i zwracanymi wartościami.

0

Kurde, coś nie idzie ;/
Moja wiedza w C# jest chyba za mała. Nie umiem sobie poradzić z tymi wątkami.
Mógłby ktoś na to spojrzeć i powiedzieć co jest źle? (odbiera tylko pierwszą wiadomość)

string retu;
        int bajty2;
        Thread th;
        int i;
        ThreadStart ts;
        Socket sok = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        public forma()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string host = ip.Text;
            if (sok.Connected)
            {
                sok.Disconnect(true);
            }
            else
            {
                sok.Connect(ip.Text, Convert.ToInt32(port.Text));
                if (sok.Connected)
                {
                    forma.ActiveForm.Text = "Połączono z " + host;
                    button1.Text = "Rozłącz";
                }
                else MessageBox.Show("Nie można połączyć z hostem", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            
            i++;
            if (sok.Connected)
            {
                byte[] msg = Encoding.UTF8.GetBytes(textBox3.Text);
                int bajty;
                bajty = sok.Send(msg, 0, msg.Length, SocketFlags.None);
                MessageBox.Show("Wyslano " + bajty.ToString());
                if (i == 1)
                {
                    ts = new ThreadStart(this.Odbierz);
                    th = new Thread(ts);
                    th.IsBackground = true;
                    th.Start();
                    th.Suspend();
                }
                else if(i == 2)
                {
                    th.Resume();
                }
                if (i >= 3)
                {
                    th.Suspend();
                    th.Resume();
                }
                    //th.Interrupt();
                
                
            }
                
            else MessageBox.Show("Musisz połączyć się z hostem!", "Informacja", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

    private void Odbierz()
    {
        while (sok.Connected)
        {
            byte[] rmsg = new byte[1024];
            sok.ReceiveTimeout = 3000;
            bajty2 = sok.Receive(rmsg, 0, 1024, SocketFlags.None);
            do
            {
               // textBox2.AppendText(Encoding.UTF8.GetString(rmsg));
                MessageBox.Show("Odebrano " + bajty2.ToString());
                retu = Encoding.UTF8.GetString(rmsg);
                bajty2 = 0;
            } while (bajty2 > 0);
            MessageBox.Show(retu);
        
        }


     
       
    }

Wiem, że głupi to wygląda...

0

Dołanczam się do temnatu z zapytaniem czy środowisko VS jest pozbawione kontrolki typu TCPClientSocket lub TCPServerSocket, coś na wzór SerialPort co można by sockety przez zdarzenia obsługiwać ?

0

Nie ma takiego czegoś. Musisz użyć Socket'a lub Tcpclient'a

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