Sockety, wysyłanie wiadomości

0

Cześć,
próbuję sobie stworzyć prosty czat pomiędzy klientem, a serwerem (z tego poradnika Gniazda sieciowe). Korzystam z TcpClient i mam pewien problem. Otóż mam sobie 3 formy - w jedna forma z dwoma przyciskami - klient i serwer, które otwierają odpowiednie formy. Otwieram klienta, a potem serwer i pojawia się wiadomość, że połączono. Problem w tym, że gdy chcę wysłać kolejną wiadomość to ona... się nie wysyła.

Serwer.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;

namespace TPC_Client
{
    public partial class Serwer : Form
    {
        public Serwer()
        {
            InitializeComponent();
            Thread watek = new Thread(CreateServer);
            watek.Start();
        }

        void CreateServer()
        {
            TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1024);
            listener.Start();
            TcpClient newClient = listener.AcceptTcpClient();
            BinaryReader reader = new BinaryReader(newClient.GetStream());
            if(listBox1.InvokeRequired)
            {
                listBox1.Invoke(new MethodInvoker(delegate
                {
                    listBox1.Items.Add(reader.ReadString());
                }));
            }
        }
    }
}

Klient.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;

namespace TPC_Client
{
    public partial class Klient : Form
    {
        TcpClient externalClient;
        BinaryWriter writer;
        //Thread watek;

        public Klient()
        {
            InitializeComponent();
            Client();
        }

        void Client()
        {
            externalClient = new TcpClient();
            if(externalClient.Connected == false)
            {
                externalClient.Connect("127.0.0.1", 1024);
                writer = new BinaryWriter(externalClient.GetStream());
                writer.Write("Nawiązano połączenie");
                writer.Write(12345.15);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            writer.Write("Próba wysłania wiadomości"); //to nie działa
        }
    }
}
0

A ta wiadomość się pojawia? writer.Write(12345.15);

Czytasz tu pierwszy string który przyjdzie

void CreateServer()
        {
            TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1024);
            listener.Start();
            TcpClient newClient = listener.AcceptTcpClient();
            BinaryReader reader = new BinaryReader(newClient.GetStream());
            if(listBox1.InvokeRequired)
            {
                listBox1.Invoke(new MethodInvoker(delegate
                {
                    listBox1.Items.Add(reader.ReadString());
                }));
            }
        }

I co dalej? Wychodzi z metody, i już nigdy więcej jej nie uruchamiasz.

0

Tą linijkę niepotrzebnie wkleiłem.

writer.Write(12345.15);

Aczkolwiek w ciągu dalszym nie wiem dlaczego mogę wysłać kolejnej wiadomości do serwera

private void button1_Click(object sender, EventArgs e)
        {
            writer.Write("Próba wysłania wiadomości");
        }

Dlaczego powyższy kod nie działa? Klikam przycisk i nic się nie dzieje...

0

No przecież napisałem, serwer odbiera tylko jedną wiadomość, dalej już nie nasłuchuje.

0

A co zrobić żeby on cały czas nasłuchiwał?

0

Nie wiem, możesz spróbować jakoś tak:

bool isWorking = true;
void CreateServer()
        {
            TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1024);
            listener.Start();
            TcpClient newClient = listener.AcceptTcpClient();
            while(isWorking)
           {
            BinaryReader reader = new BinaryReader(newClient.GetStream());
            if(listBox1.InvokeRequired)
            {
                listBox1.Invoke(new MethodInvoker(delegate
                {
                    listBox1.Items.Add(reader.ReadString());
                }));
            }}
        }

Poszukaj lepszego tutoriala, ten jest jakiś biedny.

0

Kod za bardzo nie działa, okienko z aplikacją dostaje laga, tzn nic nie można zrobić.
Polecisz może jakiś tutorial z dobrze opisanymi socketami?

0

Jak okienko przestaje odpowiadać, to oznacza, że musisz nasłuchiwanie serwera zrobić w oddzielnym wątku, a nie wątku GUI.

0

No cały czas jest w wątku, tworzę go w konstruktorze

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;

namespace TPC_Client
{
    public partial class Serwer : Form
    {
        //bool isWorking = true;
        public Serwer()
        {
            InitializeComponent();
            Thread watek = new Thread(CreateServer);
            watek.Start();
        }

        void CreateServer()
        {
            TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1024);
            listener.Start();
            TcpClient newClient = listener.AcceptTcpClient();
            while (true)
            {
                BinaryReader reader = new BinaryReader(newClient.GetStream());
                if (listBox1.InvokeRequired)
                {
                    listBox1.Invoke(new MethodInvoker(delegate
                    {
                        listBox1.Items.Add(reader.ReadString());
                    }));
                }
            }
        }
    }
}
0

pomoże ktoś? :p

0
bool isWorking = true;
void CreateServer()
        {
            TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1024);
            listener.Start();
            TcpClient newClient = listener.AcceptTcpClient();
            while(isWorking)
           {
            BinaryReader reader = new BinaryReader(newClient.GetStream());
            
            if(listBox1.InvokeRequired)//ten warunek nie ma sensu zamiast tego coś w stylu !reader.IsEmpty
            {
                listBox1.Invoke(new MethodInvoker(delegate
                {
                    listBox1.Items.Add(reader.ReadString());
                }));
            }
            Thread.Sleep(500);
}
        }

Możesz spróbować tak, w ogóle to google chyba działa u ciebie?

0

Google działa, ale nie znalazłem odpowiedzi na pytanie, więc piszę tutaj...

Co do programu - działa, tylko pod warunkiem, gdy dam Thread.Sleep(1500);
W tym przypadku wysłało się 4 razy i dalej nic nie można kliknąć ani nic...

0

F5
Wie ktoś jak zrobić aby było ciągłe nasłuchiwanie? :P

0

https://www.google.pl/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=c%23%20sockets%20server
Wynik numer 1, 2, 3, 5, chyba też 6, dalej filmików nie sprawdzałem. I jeszcze kłamiesz że w google nic nie ma?

0

Okej, udało mi się zbudować od podstaw (bazując na poradniku) własny czat pomiędzy klientem, a serwerem. Wszystko prawie działa, ale...
Łączenie z klienta z serwerem działa, ale gdy wysyłam wiadomość on każe mi się łączyć na nowo - dlaczego?

user image

Tak wygląda proces wysyłania wiadomości:

public static void SendMessage(Socket _socket, IPEndPoint _eP,string msg)
    {
        byte[] data = Encoding.ASCII.GetBytes(msg);
        _socket.SendTo(data, _eP);
    }

I po tym się pojawia wiadomość "Oczekuję na połączenie" - dlaczego, skoro ja nigdzie nie zamykałem połączenia?

0

Tak jasne, bo ktoś zobaczy screeny, dwie linijki kodu i zaraz będzie wiedział o chodzi. Pokaż cały kod.

0

klient.cs

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class SynchronousSocketClient
{
    public static void StartClient()
    {
        Socket sender = null;
        IPEndPoint remoteEP = null;
        while (true)
        {
            
            if (Console.ReadLine() == "connect")
            {
                IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
                IPAddress ipAddress = ipHostInfo.AddressList[0];
                remoteEP = new IPEndPoint(ipAddress,11000);

                sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );

                sender.Connect(remoteEP);

                Console.WriteLine("Nastąpiło połączenie z {0}", sender.RemoteEndPoint.ToString());
            }

            if(Console.ReadLine() == "send")
            {
                SendMessage(sender, remoteEP,"TestMessage<EOF>");
            }

            if(SocketConnected(sender) == false)
            {
                Console.WriteLine("Błąd: serwer jest offline");
            }
        }
    }

    public static void SendMessage(Socket _socket, IPEndPoint _eP,string msg)
    {
        byte[] data = Encoding.ASCII.GetBytes(msg);
        _socket.SendTo(data, _eP);
    }

    public static int Main(String[] args)
    {
        StartClient();
        
        while (true)
        {
            Console.ReadLine();
        }
    }

    static bool SocketConnected(Socket s)
    {
        bool part1 = s.Poll(1000, SelectMode.SelectRead);
        bool part2 = (s.Available == 0);
        if (part1 && part2)
            return false;
        else
            return true;
    }
}

serwer.cs

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class SynchronousSocketListener
{
    public static string data = null;

    public static void StartListening()
    {
        byte[] bytes = new Byte[1024];

        IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);

        Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        try
        {
            listener.Bind(localEndPoint);
            listener.Listen(10);

            while (true)
            {
                Console.WriteLine("Oczekuję na połączenie...");

                Socket handler = listener.Accept();
                Console.WriteLine("Połączono z: " + handler.RemoteEndPoint.ToString());

                data = null;

                while (true)
                {
                    bytes = new byte[2048];
                    int bytesRec = handler.Receive(bytes);
                    data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
                    if (data.IndexOf("<EOF>") > -1)
                    {
                        break;
                    }
                }

                Console.WriteLine("Odebrany tekst : {0}", data.Replace("<EOF>", ""));

                
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

        Console.WriteLine("\nWciśnij ENTER aby kontynuować");
        Console.Read();

    }

    public static int Main(String[] args)
    {
        StartListening();
        return 0;
    }
}
0

Wywal tą pętle w mainie.
Zamianst tego

if (Console.ReadLine() == "connect")
...
if(Console.ReadLine() == "send")
...

Daj:

var input = Console.ReadLine();
if (input == "connect")
...
else if(input == "send")
...

To tyle jeśli chodzi o klienta, co do serwera z którego tutka korzystałeś?
Bo nie jestem pewny czy on tak powinien przy każdym obrocie pętli akceptować połączenie

Socket handler = listener.Accept();
0

Pomoże ktoś?

0

No a co się dzieje po moich poprawkach?

0

W klient.cs zamieniłem

public static int Main(String[] args)
    {
        StartClient();
 
        while (true)
        {
            Console.ReadLine();
        }
    }
 

na

public static int Main(String[] args)
    {
        StartClient();
        
        
            Console.ReadLine();
            return 0;
        
    }

i dalej to samo...

0

No a druga część mojego posta?
Rozumiesz że program czeka aż wpiszesz connect, później send, przy następnym obrocie pętli znowu czeka na connect?

0

Dzięki za nakierowanie, ogarnąłem sobie już to :) Mam jeszcze jedno pytanie - można nazwać socketowi jakąś nazwę abym mógł rozpoznać kto się łączy?

0

Nie wiem.
Możesz wysyłać te wiadomości jakimś wymyślonym przez siebie protokołem, np:
Client1|Client2|Cześć
Później dajesz

var message = income.Split('|');

I możesz przyjąć że message[0] - nadawca, message[1] - odbiorca, message[2] - wiadomość

0

Okej, a jeszcze jest sprawa - da się aby jedno okno było i klientem, i serwerem? Oprócz odbierania wiadomości przydałoby się je jeszcze wysyłać.

0

No klient powinien też nasłuchiwać w drugim wątku. Klient wysyła wiadomość do serwera, serwer wysyła ją dalej.

0

Serwerom mam nadawać losowe porty (0-65535)? Czy jak, bo przy włączaniu drugiego serwera jeden z nich mi się crashuje..

0

Dobra poradziłem sobie :D

0

siema mógł byś udostępnić cały kod? bardzo mnie ciekawi taka aplikacja chętnie bym ja przetestował z bratem :3

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