antonis_wrx Δημοσ. 20 Μαρτίου 2009 Δημοσ. 20 Μαρτίου 2009 Καλησπέρα. Προσπαθώ να φτιάξω τον server σε μια εφαρμογή. Το σενάριο είναι το εξής: οι χρήστες client συνδέονται με tcp (sockets) και στέλνουν μηνύματα (strings με βάση ένα πρωτόκολλο) στον server ο οποίος τα αποθηκεύει σε μια db αφού τα κάνει parse. Ο κάθε client ανοίγει δικό του thread στον server όταν συνδέεται. Αυτό που δεν ξέρω πως να κάνω είναι, μόλις ένας client στείλει κάτι, ο server να ενημερώσει μια ομάδα από άλλους clients και να τους στείλει την πληροφορία αυτή.
alex2005 Δημοσ. 20 Μαρτίου 2009 Δημοσ. 20 Μαρτίου 2009 Ε πρέπει να κρατάς μία λίστα με τους συνδεδεμένους clients.( Η οποία καλό είναι να ενημερώνεται με αιτήσεις τύπου ping από τον server στους client). Μετά ο κάθε client πρέπει να έχει ένα socket ανοιχτό για να λαμβάνει τα μηνύματα από τον server.
Evgenios1 Δημοσ. 20 Μαρτίου 2009 Δημοσ. 20 Μαρτίου 2009 Δε με λες .. γτ εχω σκαλοσει. εχω αυτον εδω το σερβερ >using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; namespace Server { class Program { public delegate void OnConnectHandler(Socket sok); static event OnConnectHandler Connected; static void Main(string[] args) { Connected += new OnConnectHandler(Program_Connected); Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 1010); server.Bind(endpoint); server.Listen(10); while (true) { try { Connected(server.Accept()); } catch (SocketException so) { Console.WriteLine(so.Message); } } } static void Program_Connected(Socket sok) { byte[] buffer = new byte[32]; while (sok.Connected) { try { sok.Receive(buffer); sok.Send(Encoding.ASCII.GetBytes("Connected to srv")); Console.WriteLine(Encoding.ASCII.GetString(buffer)); } catch { } } } } } και τουτον εδω το πελατη >using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; namespace client1 { class Program { static void Main(string[] args) { clientA obj = new clientA(); while (true) { string s = Console.ReadLine(); obj.Send(s); } } public class clientA { Socket client; IPEndPoint eip; public clientA() { client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); eip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1010); try { client.Connect(eip); } catch { } } public void Send(string msg) { byte[] buffer = Encoding.ASCII.GetBytes(msg); try { client.Send(buffer); buffer = new byte[32]; client.Receive(buffer); Console.WriteLine(Encoding.ASCII.GetString(buffer)); } catch { } } } } } το προβλημα μου ειναι οτι, οτανενας πελατης ειναι συνδεδεμενος με το σερβερ , δε μπορει να συνδεθει αλος πελατης (?!!) .(βασικα ο αλος πελατης πεπιμενει να αποσυνδεθει ο πρωτος για να συνδεθει αυτος). Ξερεις τι να φτεει( και thread δοκιμασα αλλα @@)
antonis_wrx Δημοσ. 20 Μαρτίου 2009 Μέλος Δημοσ. 20 Μαρτίου 2009 μιλάμε για clients οι οποίοι θα είναι συνδεδεμένοι εκείνη την στιγμή.. δηλαδή το πρόβλημα μου είναι το πως θα καταλάβουν τα άλλα thread στον server ότι πρέπει να στείλουν πληροφορία. άμα γίνεται fire το event από το thread του client που έστειλε την πληροφορία και έχουν όλα τα thread listener θα δουλέψει; υπάρχουν κάπου παράδειγμα για κάτι τέτοιο; για μου φαίνεται αρκετά μπερδεμένο..
alex2005 Δημοσ. 20 Μαρτίου 2009 Δημοσ. 20 Μαρτίου 2009 Μία υλοποίηση που έρχεται γρήγορα στο μυαλό μου. (Κοίταξα πρόχειρα τον κώδικα γιατί δεν είναι η .Net η ειδικότητά μου). Έχεις αυτό το πρόβλημα υποθέτω γιατί μπορεί ένας client να απασχολεί για πολύ τον server. Αν τα πακέτα ήταν μεγέθους μερικών bytes δεν θα υπήρχε αυτό το πρόβλημα, καθώς η αναμονή θα ήταν μικρή. Οπότε θα μπορούσες να κάνεις το εξής. Να κάνεις ένα σύστημα με tokens. Δηλαδή, ο client να ζητάει επικοινωνία από τον server, και ο server να απαντάει με ένα token (μοναδικό αριθμό). Ο server παράλληλα να κρατάει ένα Map με τον token και το reference σε ένα thread (ή έστω την instance ενός object που παίζει τον ρόλο του buffer). Έτσι όλα τα πακέτα φτάνουν στο βασικό thread και αυτό τα πετάει στα υπόλοιπα thread/instances μίας class, το οποίο θα κάνει και αυτό που πρέπει να κάνει. Οπότε οι client μετά κόβουν τα δεδομένα σε μικρά πακέτα και τα στέλνουν μαζί με το token. Σίγουρα υπάρχει και καλύτερος τρόπος, αλλά είναι και αυτή μία λύση.
Evgenios1 Δημοσ. 20 Μαρτίου 2009 Δημοσ. 20 Μαρτίου 2009 Αφου κανω ενα instan με καθε συνδεση socket sok=server.Accept(); <--
alex2005 Δημοσ. 21 Μαρτίου 2009 Δημοσ. 21 Μαρτίου 2009 Βασικά η σύνδεση πρέπει να είναι μία, αφού δεν μπορείς να κάνεις Bind την ίδια port πάνω από μία φορά. Οπότε όπως έχεις το while (true) loop, μόνο που όταν λαμβάνεις το πακέτο θα πρέπει να το κάνεις forward στο κατάλληλο instance, για να κάνεις ότι θέλεις να κάνεις. Τα instances από την άλλη μπορούν να στείλουν όλα "μαζί" απαντήσεις στους client.
Evgenios1 Δημοσ. 21 Μαρτίου 2009 Δημοσ. 21 Μαρτίου 2009 forward εννοεις? δε γινεται να ειναι δυο συνδεσεις ταυτοχρονα σε ενα σερβερ ? (ο καθε πελατης εχει διαφορετικη πορτα)
alex2005 Δημοσ. 21 Μαρτίου 2009 Δημοσ. 21 Μαρτίου 2009 μιλάμε για clients οι οποίοι θα είναι συνδεδεμένοι εκείνη την στιγμή.. δηλαδή το πρόβλημα μου είναι το πως θα καταλάβουν τα άλλα thread στον server ότι πρέπει να στείλουν πληροφορία. άμα γίνεται fire το event από το thread του client που έστειλε την πληροφορία και έχουν όλα τα thread listener θα δουλέψει; υπάρχουν κάπου παράδειγμα για κάτι τέτοιο; για μου φαίνεται αρκετά μπερδεμένο.. Δεν κρατάς references από αυτά τα thread? Αν κρατάς τότε απλά μπορείς όταν έρθει ένα μήνυμα από κάπου να τα ενημερώνεις, αν όχι τότε κακώς . Τώρα βέβαια, μπερδεύτηκα με αυτό που λες για clients που είναι συνδεδεμένοι εκείνη την στιγμή. Γιατί η έννοια της σύνδεσης δεν είναι συνεχής, αλλά ασυνεχής. (δεν είναι και η καλύτερη εξήγηση αυτή ) Αυτό που εννοώ είναι ότι ένας client στέλνει περιοδικά πακέτα στον server, και αυτό τον κάνει να είναι λογικά συνδεδεμένος (πολύ χοντρικό αυτό αλλά τέλος πάντων). Παρόλα ταύτα δεν υπάρχει κάτι άλλο που να υποδηλώνει ότι ένας client είναι συνδεδεμένος. Κατά συνέπεια για να ξέρεις ποιοι client είναι συνδεδεμένοι πρέπει να κρατάς κάπου στην μνήμη μία λίστα από clients που πρόσφατα σου έστειλαν κάποιο πακέτο, ή τέλος πάντων είναι λογικά συνδεδεμένοι σύμφωνα με το δικό σου πρωτόκολλο. Μετά η διαδικασία είναι να στείλεις ότι θέλεις σε αυτήν την λίστα από clients. Όσο αναφορά τα threads, έχεις κάνει κάτι παρόμοιο με αυτό που πρότεινα στον Ευγένιο? Αν όχι τότε έχω την αίσθηση ότι ενδέχεται να έχεις thread τα οποία τρέχεις να μην σταματάνε ποτέ, το οποίο είναι μέγα λάθος καθώς όσο δουλεύει η εφαρμογή θα τρώει συνέχεια πόρους μέχρι τελειώσει το heap space και να τερματιστεί βιαίως η εφαρμογή. Γενικότερα δώσε λίγες περισσότερες πληροφορίες για την υλοποίηση για να καταλάβουμε πως είναι στημένο αυτό που έχεις κάνει. forward εννοεις? δε γινεται να ειναι δυο συνδεσεις ταυτοχρονα σε ενα σερβερ ? (ο καθε πελατης εχει διαφορετικη πορτα) Ναι θα μπορούσε ο κάθε client να έχει διαφορετική port, αλλά δεν είναι και ότι καλύτερο να κάνεις bind διαφορετική port για κάθε client. Τυπικά ένας server χρησιμοποιεί μία port και πολλές processes/threads τα οποία εξυπηρετούν τους πελάτες.
Evgenios1 Δημοσ. 21 Μαρτίου 2009 Δημοσ. 21 Μαρτίου 2009 δοκιμασα και με threads, δλδ εκανα > List<Thread> Childrens = new List<Thread>(); ..... object conn = server.Accept(); ParameterizedThreadStart pThread = new ParameterizedThreadStart(Program_Connected); pThread.Invoke(conn); Childrens.Add(new Thread(pThread)); Childrens[Childrens.Count - 1].Start(); ...... Αλλα.. τιποτα... μονο αν κανω disconnect απο το πελατη μπορει να κανει connect ο επομενος Φρικη!!!!!!!!!!!!!!!!!!!!!!!
alex2005 Δημοσ. 21 Μαρτίου 2009 Δημοσ. 21 Μαρτίου 2009 δοκιμασα και με threads, δλδ εκανα > List<Thread> Childrens = new List<Thread>(); ..... object conn = server.Accept(); ParameterizedThreadStart pThread = new ParameterizedThreadStart(Program_Connected); pThread.Invoke(conn); Childrens.Add(new Thread(pThread)); Childrens[Childrens.Count - 1].Start(); ...... Αλλα.. τιποτα... μονο αν κανω disconnect απο το πελατη μπορει να κανει connect ο επομενος Φρικη!!!!!!!!!!!!!!!!!!!!!!! Μα ναι, εννοείται πως πρέπει να αποσυνδεθεί ο client για να συνδεθεί ο επόμενος. Να γίνουν δύο πράγματα πραγματικά ταυτόχρονα σε υπολογιστή σαν έννοια απλά δεν υφίσταται. Πόσο απασχολεί ο client τον server? Δηλαδή τι κάνεις ? Ανταλλαγή αρχείων ας πούμε ? Τέλος πάντων, ήρθε η ώρα για νάνι τώρα. Καλό κουράγιο αν το τραβήξετε και άλλο σήμερα.
snowPrincess Δημοσ. 21 Μαρτίου 2009 Δημοσ. 21 Μαρτίου 2009 Δες αν σε βοηθάει το MVC design pattern. Ciao.
vandermonde Δημοσ. 27 Μαρτίου 2009 Δημοσ. 27 Μαρτίου 2009 τελικα αν εχουμε τον server και 2 (or more) clients συνδεδεμενους, υπαρχει τροπος ο σερβερ (μετα π.χ απο απαιτηση ενος client) νσ στειλει το οτιδηποτε σε καποιον αλλο client και οχι σε αυτον που του κανε το request? κατεβασα ebooks για tcp και java, διαβασα το tutorial της sun κλπ αλλα ακρη (λογω χαζομαρας?) δεν εβγαλα....
alex2005 Δημοσ. 28 Μαρτίου 2009 Δημοσ. 28 Μαρτίου 2009 τελικα αν εχουμε τον server και 2 (or more) clients συνδεδεμενους, υπαρχει τροπος ο σερβερ (μετα π.χ απο απαιτηση ενος client) νσ στειλει το οτιδηποτε σε καποιον αλλο client και οχι σε αυτον που του κανε το request? κατεβασα ebooks για tcp και java, διαβασα το tutorial της sun κλπ αλλα ακρη (λογω χαζομαρας?) δεν εβγαλα.... Φυσικά και υπάρχει τρόπος. Μπορείς να δεις έναν τρόπο αν διαβάσεις πιο πάνω σε αυτό το thread. Αν γενικότερα δεν είμαι κατανοητός σε αυτά που έχω πει παρακαλώ να μου το πείτε
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.