bokarinho Δημοσ. 5 Δεκεμβρίου 2009 Δημοσ. 5 Δεκεμβρίου 2009 Θέλω να περάσω έναν πίνακα βασικά σε κάθε παιδί που θα διαχειρίζεται τον καθένα client ο οποίος πίνακας θα ανανεώνεται συνεχώς από τον πατέρα και γι αυτό θέλω κάθε φορά τα παιδία να έχουν την ανανεωμένη έκδοση.. Συναντάω βασικά δυσκολία με την pipe()... πώς θα περάσω για παράδειγμα τον ακέραιο α από το παιδί στον πατέρα και πώς έναν πίνακα ακεραίων για να καταλάβω πώς λειτουργεί...?? Μπορείτε να διορθώσεται στον παρακάτω κώδικα.. >#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main() { int pfds[2], a = 0; pipe(pfds); if (!fork()) { printf(" CHILD: writing to the pipe\n"); a = 55; write(pfds[1], a, sizeof (a)); printf(" CHILD: exiting\n"); exit(0); } else { printf("PARENT: reading from pipe\n"); read(pfds[0], a, sizeof (a)); printf("PARENT: read \"%d\"\n", a); wait(NULL); } } Τα pipes χρησιμοποιούνται για IPC όπως σωστά και έχει αναφερθεί, αυτό που σου διαφεύγει είναι ότι για να χρησιμοποιήσεις σωστά τα pipes η μία process δηλαδή η parent process εκτελεί την fork για να δημιουργήσει μία child process και με την χρήση του σωλήνα να κάνουν την δουλειά. Για να γίνει αυτό σωστά όμως πρέπει να ξέρουμε προς τα που θέλουμε να πάει η πληροφορία. Αν θέλεις να στείλεις πληροφορία από το παιδί προς τον πατέρα τότε πρέπει τότε ο πατέρας πρέπει να κλείσει το write του και το παιδί πρέπει να κλείσει το read end του. Τι εννοώ με αυτό: Όταν ορίζεις ως int FileDesc[2]; στην main σου και περνάς το όρισμα μέσα από την pipe function (την οποία και κακώς δεν εξετάζεις τι επιστρέφει) τότε ο σωλήνας δημιουργείται και έχει 2 άκρα, Στο μηδέν είναι το read δηλαδή το άκρο που διαβάζει την πληροφορία, στο ένα είναι το write δηλαδή το άκρο που γράφει την πληροφορία. Το ίδιο ισχύει και για το παιδί, οπότε για να γίνει σωστά η διαδικασία πρέπει να κλείσουμε το write end του πατέρα με την close(FileDesc[1]); και μετά να κάνουμε read και στο παιδί πρέπει να κλείσουμε το read end δηλαδή close(FileDesc[0]); και μετά να κάνουμε write. Οπότε βάλε τις close σωστά στον κώδικα και μετά το συζητάμε, Bokarinho.
karabouzouk... Δημοσ. 5 Δεκεμβρίου 2009 Μέλος Δημοσ. 5 Δεκεμβρίου 2009 Σε ευχαριστώ πολύ.. σωστός.... Για όποιον άλλο συναντάει δυσκολία έτσι είναι το σωστό... Και χωρίς "&" στη μεταβλητή α αν είναι πίνακας.. >#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main() { int pfds[2], a = 0; pipe(pfds); if (!fork()) { close(pfds[0]); printf(" CHILD: writing to the pipe\n"); a = 55; write(pfds[1], &a, sizeof(a)); printf(" CHILD: exiting\n"); exit(0); } else { close(pfds[1]); printf("PARENT: reading from pipe\n"); read(pfds[0], &a, sizeof(a)); printf("PARENT: read \"%d\"\n", a); wait(NULL); } }
karabouzouk... Δημοσ. 7 Δεκεμβρίου 2009 Μέλος Δημοσ. 7 Δεκεμβρίου 2009 Επειδή η pipe() δεν με βόλεψε και τόσο πολύ έψαξα λίγο και βρήκα εδώ ότι μπορώ και με shared memory να κάνω αυτό που θέλω... να έχω κοινά δεδομένα δηλαδή μεταξύ διεργασιών.. Αλλά τρέχωντας κάποιον έτοιμο κώδικα που έχει στη σελίδα όταν πάει να καλέσει μια συνάρτιση βγάζει αυτό το error--> /cygdrive/c/Program Files/NetBeans 6.1/cnd2/bin/dorun.sh: line 103: 11472 Bad system call "$pgm" "$@" Ξέρει κανείς που οφείλεται αυτό..? Έχω netβeans και compiler cygwin σε XP λειτουργικό... Αν δεν ξέρεται κάποια λύση σε αυτό έχετε να πρωτείνεται κάτι άλλο που μπορώ να κάνω σχετικά με την κοινή μνήμη μεταξύ διεργασιών..?
javavall Δημοσ. 8 Δεκεμβρίου 2009 Δημοσ. 8 Δεκεμβρίου 2009 Κοινή μνήμη..(?) Έρχεσαι στα λόγια μου . Γιατί δεν φτιάχνεις το πρόγραμμα σε linux? Τόσο καιρό που παιδεύεσαι θα είχες φτιάξει όχι μόνο server-client... H IPC shared memory στο site που έδειξες χρησιμοποιεί βιβλιοθήκες που δεν υπάρχουν στα windows... Εάν ήταν τόσο εύκολο να τις μεταφέρεις(εάν γίνεται κιόλας) ώστε να λειτουργούν σε windows, δεν θα μας παιδεύανε στη σχολή να μάθουμε τα linux ή έστω να χρησιμοποιήσουμε Vmware για τις εργασίες μας. ps: Καλύτερη λύση είναι και τα threads( πχ POSIX threads, unix πάλι...), διότι η κοινή μνήμη που μπορείς να δεσμεύσεις είναι πολύ περιορισμένη...
karabouzouk... Δημοσ. 8 Δεκεμβρίου 2009 Μέλος Δημοσ. 8 Δεκεμβρίου 2009 .....όπως το κόβω η μόνη λύση αυτή είναι.. απλά ήθελα να δω αν κάνω τίποτα λάθος εγώ.. αν κάποιος έχει κάτι άλλο να πρωτείνει ας το πει εδώ.. Και σαν offtopic πείτε μια καλή έκδοση του linux.. είχα τα open suse ένα φεγγάρι.. λέτε να τα ξαναπρωτιμήσω..?
yourse.gr Δημοσ. 8 Δεκεμβρίου 2009 Δημοσ. 8 Δεκεμβρίου 2009 στο offtopic : http://wiki.linuxquestions.org/wiki/Choosing_a_Linux_distribution ps: Καλύτερη λύση είναι και τα threads( πχ POSIX threads, unix πάλι...), διότι η κοινή μνήμη που μπορείς να δεσμεύσεις είναι πολύ περιορισμένη... Καλύτερη λύση είναι WSAAsyncSelect() και για linux δές epoll
F i L Δημοσ. 25 Δεκεμβρίου 2009 Δημοσ. 25 Δεκεμβρίου 2009 Γίνεται να έχεις κοινή μνήμη με sockets? Αυτό δεν χρησιμοποιείται για IPC?
karabouzouk... Δημοσ. 11 Ιανουαρίου 2010 Μέλος Δημοσ. 11 Ιανουαρίου 2010 http://beej.us/guide/bgnet/output/html/multipage/index.html Ένας από τους καλύτερους οδηγούς για Network Programming σε C για αρχάριους μέχρι και αρκετά πιο ψαγμένους που έχω διαβάσει αυτόν τον καιρό που άρχισα να ασχολούμαι με το αντικείμενο.. Όποιος έχει κάποια σχετική απορία ας του ρίξει μια ματιά είναι πολύ κατανοητός, πλήρης και σε πιασιάρικη γλώσσα..! Ελπίζω να βοήθησα τους νεώτερους..!
karabouzouk... Δημοσ. 13 Ιανουαρίου 2010 Μέλος Δημοσ. 13 Ιανουαρίου 2010 Έχω το εξής πρόβλημα... Στο πρόγραμμα του client θέλω να μπορώ να στέλνω όποτε ο χρήστης πληκτρολογεί κάποιο μύνημα με τη send() αλλά ταυτόχρονα να ελέγχω και αν υπάρχει κάποιο μύνημα από το server με τη recv να τρέχει συνέχεια.. Μάλλον αυτό πρέπει να το κάνω σε διαφορετικά threads και έχω χρησιμοποιήσει τη fork γι αυτό.... αλλά κάθε φορά σε όσες δοκιμές έκανα η διεργασία "παιδί" είτε είναι η send είτε η recv μου βγάζει σφάλμα 10093... Το σίγουρο είναι ότι κάτι δεν κάνω σωστά ή κάτι δεν έχω καταλάβει.. ορίστε και ο κώδικας μήπως βγάλετε άκρη... >#include <winsock2.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <unistd.h> #define END_SENDING "exit" #define DEFAULT_server_addr_IP "192.168.1.2" #define DEFAULT_PORT 2010 #define DEFAULT_PROTO SOCK_STREAM #define BUFF_SIZE 1024 int main(void) { char SendBuffer[bUFF_SIZE], RecvBuff[bUFF_SIZE]; int retval; int pid; WSADATA wsaData; SOCKET server_socket; SOCKADDR_IN server_addr; if ((retval = WSAStartup(0x202, &wsaData)) != 0) { fprintf(stderr, "Client: WSAStartup() failed with error %d\n", retval); WSACleanup(); return -1; } else { printf("Client: WSAStartup() is OK.\n"); } server_addr.sin_addr.s_addr = inet_addr(DEFAULT_server_addr_IP); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(DEFAULT_PORT); server_socket = socket(AF_INET, DEFAULT_PROTO, 0); if (server_socket < 0) { fprintf(stderr, "Client: Error Opening socket: Error %d\n", WSAGetLastError()); WSACleanup(); return -1; } else { printf("Client: socket() is OK.\n"); } printf("Client connecting to: %s.\n", DEFAULT_server_addr_IP); if (connect(server_socket, (struct sockaddr*) & server_addr, sizeof (server_addr)) == SOCKET_ERROR) { fprintf(stderr, "Connect() failed: %d\n", WSAGetLastError()); WSACleanup(); exit(5); } else { printf("Connect() is OK.\n"); } pid = fork(); if (pid < 0) { printf("ERROR on fork"); } else if (pid == 0) { while (1) { retval = recv(server_socket, RecvBuff, sizeof (RecvBuff), 0); if (retval < 0) { printf("recv() failed: error %d.\n", WSAGetLastError()); } else if (retval > 0) { printf("\n-> %s", RecvBuff); } else { printf("Server down...\n"); } } exit(5); } else { while (1) { scanf("%s", SendBuffer); if (strcmp(SendBuffer, END_SENDING) == 0) { break; } retval = send(server_socket, SendBuffer, sizeof (SendBuffer), 0); if (retval == SOCKET_ERROR) { fprintf(stderr, "Client: send() failed: error %d.\n", WSAGetLastError()); } } closesocket(server_socket); WSACleanup(); return 0; } } Ευχαριστώ για την όποια πρόταση/βοήθεια...
C6WGMN Δημοσ. 13 Ιανουαρίου 2010 Δημοσ. 13 Ιανουαρίου 2010 Η fork φτιάχνει καινούργιες διαδικασίες (process), και όχι threads. Εγώ προτείνω κάτι πιο απλό: man 2 select
karabouzouk... Δημοσ. 13 Ιανουαρίου 2010 Μέλος Δημοσ. 13 Ιανουαρίου 2010 Η fork φτιάχνει καινούργιες διαδικασίες (process), και όχι threads. Εγώ προτείνω κάτι πιο απλό: man 2 select Μήπως μπορείς να μου εξηγήσεις λίγο περισσότερο τι εννοείς...? Αν μου έδεινες κάποιο παράδειγμα ίσως να καταλάβαινα καλύτερα.. Ευχαριστώ για την απάντηση σου!
Evgenios1 Δημοσ. 14 Ιανουαρίου 2010 Δημοσ. 14 Ιανουαρίου 2010 WSAAsyncSelect Καλη τυχη Καπου πηρε το ματι μου οτι ειναι καλο να αποφευγεις threads σε socket.
karabouzouk... Δημοσ. 14 Ιανουαρίου 2010 Μέλος Δημοσ. 14 Ιανουαρίου 2010 Καπου πηρε το ματι μου οτι ειναι καλο να αποφευγεις threads σε socket. Διάβασα την σελίδα για την WSAAsyncSelect αλλά δεν κατάφερα να τη δοκιμάσω... Έτσι συντάσεται.. int WSAAsyncSelect(__in SOCKET s, __in HWND hWnd, __in unsigned int wMsg, __in long lEvent); Εγώ προγραμματίζω σε απλή C.. στη δεύτερη παράμετρο τί πρέπει να βάλω...? Έχεις πρόχειρο κάποιο απλό παράδειγμα για να καταλάβω καλύερα πώς θα την χρησιμοποιήσω....? Ίσως να την προσάρμωζες στον κώδικα που έχω γράψει αν δε σου κάνει κόπο αλλά και ένα απλί παράδειγμα αρκεί.. ευχαριστώ..
Evgenios1 Δημοσ. 14 Ιανουαρίου 2010 Δημοσ. 14 Ιανουαρίου 2010 Δεν το εχω δοκιμασει ποτε μου. hWnd ειναι ο window handler. Νομιζω οτι μπορεις να το προσπερασεις με χρηση τοθ NetworkEvent. Αυτο το API δουλευει με events για αυτο και σου φαινεται περιεργο. Να ενα πολυ καλο παραδειγμα ΕΔΩ
karabouzouk... Δημοσ. 29 Ιανουαρίου 2010 Μέλος Δημοσ. 29 Ιανουαρίου 2010 Τα δύο προγράμματα (Client και Server) είναι έτοιμα και δουλεύουν κανονικά. Αλλά δουλεύουν κανονικά μόνο όταν είναι στο ίδιο δίκτυο ο server και οι Clients.. Τώρα θέλω να μου πείτε τον καλύτερο τρόπο για να μπορέσω να συνδεθώ στο server μου από έναν υπολογιστή εκτώς του ιδιοτικού δικτύου.. από οπουδήποτε στο internet.. Ξέρω ότι πρέπει να κάνω Port Forward στο router μου την πόρτα που χρησιμοποιώ στα προγράμματα μου για να μην κόβωνται τα πακέτα... είναι λίγο μπελαλήδικη δουλειά αλλά δεν θα παραπονιόμουν αν δούλευε κιόλας..!! Με λίγο ψάξιμο στο ίντερνετ βρήκα κάποια προγραμματάκια που μπορείς να διαχειρίζεσαι τις πόρτες του router μέσο UPnP (ενεργοποιώντας την επιλογή στο router) αλλά ούτε με αυτό τα κατάφερα Έχετε καμία σίγουρη λύση..? κάτι που χρησιμοποιείται για αυτή τη δουλειά..? Ευχαριστώ πολύ!
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.