Laden...

Asynchroner Socket, Verbindung halten?

Erstellt von kpatrickk vor 17 Jahren Letzter Beitrag vor 17 Jahren 2.330 Views
K
kpatrickk Themenstarter:in
139 Beiträge seit 2007
vor 17 Jahren
Asynchroner Socket, Verbindung halten?

Hallo,

ich möchte gerne eine feste Verbindung von einem Server zu einem Klienten haben. Die Verbindung port und so soll am Anfang ausgemacht werden und wenn die Verbindung steht soll sie gehalten werden bis sich der client abmeldet.

Bei den msdn Beispiel... wird jedesmal eine neue Verbindung hergestellt.

Bei beginreceive habe ich folgendes gefunden:


public static void Listen_Callback(IAsyncResult ar){
     allDone.Set();
     Socket s = (Socket) ar.AsyncState;
     Socket s2 = s.EndAccept(ar);
     StateObject so2 = new StateObject();
     so2.workSocket = s2;
     s2.BeginReceive(so2.buffer, 0, StateObject.BUFFER_SIZE,0,
	                       new AsyncCallback(Async_Send_Receive.Read_Callback), so2);	
}




Wie kann ich die Information des ports speichern? Ich möchte bei dem ersten verbindungsaufbau einen port bekommen und anschließend immer wieder verwenden. Also auch kein socket.Close()...

Ich wäre für Hilfe sehr dankbar. Es gibt es bereits einige beispiele hier zu tcp/ip und sockets aber ich habe es leider noch nicht geschafft auf meine Anwendung umzustellen. Wie kann ich das stateobject am besten sichern?

Vielen Dank

T
94 Beiträge seit 2006
vor 17 Jahren

hallo,

ich versteh nicht wo das problem ist.
die verbindung wird erst beendet wenn du socket.Close() aufrufst oder eine der verbindungen abgebrochen wird!

zudem versteh ich nich wieso du ein stateobject erstellst? du kannst doch direkt das socket objekt übergeben.
kannst dir auch mal das anschauen:
sockets frage (irc verbindung) (3. post, interessant für dich: OnConnect OnReceive OnSend)

so hatte ich eine irc connection aufgebaut. vielleicht hilft dir das weiter.

mfg

If you don't like me for who I am, then you don't like me for who I am, but all you're gonna get, is who I am.

K
kpatrickk Themenstarter:in
139 Beiträge seit 2007
vor 17 Jahren

Der Sever sieht so aus:



while (true) {
                // Set the event to nonsignaled state.
                allDone.Reset();

                // Start an asynchronous socket to listen for connections.
                Console.WriteLine("Waiting for a connection...");
                listener.BeginAccept( 
                    new AsyncCallback(AcceptCallback),
                    listener );

                // Wait until a connection is made before continuing.
                allDone.WaitOne();
            }

Hier wird eine Verbindung aufgebaut, eine Nachricht vopm Clienten empfangen, geantwortet und dann die Verbindung zurückgesetzt.
Wie gehe ich vor wenn ich die Verbindung nicht zurücksetzen möchte?

Verwende ich weitehin beginaccept und trage in eine Client Liste alle Clients ein, die ich kenne. Falls eine neue Anfrage kommt wird dann diese Liste überprüft. Falls ein Client dort vorhanden ist wird über den Socket in der Liste geantwortet?

Oder erstelle ich einen Thread, der auf dem Port einen Listener verwendet und immer wenn ein neuer Client erscheint einen neuen Thread für disen anlegt, der auf Nachrichten wartet?

T
94 Beiträge seit 2006
vor 17 Jahren

da ich gerade keine lust habe einen längeren post zu schreiben und außer mir anscheinend keiner hier im forum etwas zu threads über asynchronen sockets schreibt, werd ich dir mal ein beispiel posten:


        public void startlisten()
        {
            Listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint iep = new IPEndPoint(IPAddress.Loopback, 10000); // für 127.0.0.1, also nur zum testen gedacht
            Listener.Bind(iep);
            Listener.Listen(1); // lässt eine verbindung zu. kannste ändern
            Listener.BeginAccept(new AsyncCallback(SOnConnectRequest), Listener);
        }
        public void SOnConnectRequest(IAsyncResult ar)
        {
            Socket oldlistener = (Socket)ar.AsyncState;
            SClient = oldlistener.EndAccept(ar);
            SClient.BeginReceive(sdata, 0, size, SocketFlags.None, new AsyncCallback(SOnReceive), SClient);
        }
        public void SOnReceive(IAsyncResult ar)
        {
            Socket remote = (Socket)ar.AsyncState;
            int recv = remote.EndReceive(ar);
            if (recv == 0)
            {
                remote.Close();
                Listener.BeginAccept(new AsyncCallback(SOnConnectRequest), Listener);
            }
            string receivedtext = Encoding.ASCII.GetString(sdata, 0, recv);
            Invoke(tttgetstring, new string[] { receivedtext });
            remote.BeginReceive(sdata, 0, size, SocketFlags.None, new AsyncCallback(SOnReceive), remote);
        }
        public void SOnSend(IAsyncResult ar)
        {
            Socket remote = (Socket)ar.AsyncState;
            int sent = remote.EndSend(ar);
            remote.BeginReceive(sdata, 0, size, SocketFlags.None, new AsyncCallback(SOnReceive), remote);
        }
        private Socket Listener;
        private Socket SClient;
        private byte[] sdata = new byte[4096];
        delegate void TTTGetStrings(string msg);
        private event TTTGetStrings tttgetstring;
        void OnStringInterpret(string msg)
        {
            // msg = ankommende nachricht hier kannste mit machen was de willst
        }
        // tttgetstring = new TTTGetStrings(OnStringInterpret); // das am besten beim formaufbau 

das, was du nicht verstehst, bitte erst einmal in der msdn library nachschlagen. falls du danach noch fragen hast, grad wieder hier rein.

mfg

//edit: size kannste durch "sdata.Length" ersetzen. oder "private int size = 4096;" einfügen

If you don't like me for who I am, then you don't like me for who I am, but all you're gonna get, is who I am.

K
kpatrickk Themenstarter:in
139 Beiträge seit 2007
vor 17 Jahren

Vielen Dank für die Tips,

ich habe jetzt eine Lösung die funktioniert.

Zu dem Auflösen der Verbindung verschicke ich vom Client eine Message mit "quit<EOF>". Wenn diese empfangen wird antwortet der Server mit der selben Nachricht. Anschließend schließt der Server die Message:


client.Shutdown(SocketShutdown.Both);
                    client.Close();

Nach dem der Client die quit bestätigung empfangen hat schließt er ebenfalls die Verbindung.

Ist das so richtig? Wenn ich mit netstat die ports betrachte hat der verwendete Port... anschließend den Status Warten. Irgendwann wird er dann nicht mehr angezeigt. Das ist so richtig oder?

P.s. falls jemand dazu einen Link kennt wo dies genauer Beschrieben wird, dann bitte mitteilen...

Patrick