Προς το περιεχόμενο

Client-Server πρόγραμμα στη C με sockets


karabouzouk...

Προτεινόμενες αναρτήσεις

Δημοσ.

Πριν λίγες μέρες άρχισα να ασχολούμαι με τη χρήση sockets στη C και μας δόθηκαν και κάποια ενδεικτικά προγράμματα στη σχολή...

Έχω καταλάβει γενικά τις βασικές συναρτήσεις που χρησιμοποιούνται για τη σύνδεση server-client και προσπαθώ να προχωρίσω λίγο παραπάνω..

Θα ήθελα κάποιος με απλά λόγια καθώς είμαι αρχάριος να μου εξηγήσει το σκεπτικό για να συνδέσω παραπάνω από ένα υπολογιστές(client) σε ένα server..

Στα προγράμματα που έχω γίνεται αυτό με τη listen() που βάζει σε ουρά τις εισερχόμενες αιτήσεις για σύνδεση και μετά με μια επανάληψη τις δεχόμαστε με την accept() και τις διαχειριζόμαστε μια μια σειρικά...(καλά τα λέω?)

Όταν εξηπηρετηθεί ένας client της ουράς τι γίνεται..? αποσυνδέεται και πρέπει να ξανασυνδεθεί για να ξαναεξυπηρετηθεί..? ή παραμένει συνδεδεμένος και εξυπηρετήται μόλις εξυπηρετηθούν και οι άλλοι clients...?

 

Αυτός είναι ο κώδικας για server και client που έχω...

 

server

>#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DEFAULT_PORT 2007
// default TCP socket type
#define DEFAULT_PROTO SOCK_STREAM

void Usage(char *progname) {
   fprintf(stderr, "Usage: %s -p [protocol] -e [port_num] -i [ip_address]\n", progname);
   fprintf(stderr, "Where:\n\t- protocol is one of TCP or UDP\n");
   fprintf(stderr, "\t- port_num is the port to listen on\n");
   fprintf(stderr, "\t- ip_address is the ip address (in dotted\n");
   fprintf(stderr, "\t  decimal notation) to bind to. But it is not useful here...\n");
   fprintf(stderr, "\t- Hit Ctrl-C to terminate server program...\n");
   fprintf(stderr, "\t- The defaults are TCP, 2007 and INADDR_ANY.\n");
   WSACleanup();
   exit(1);
}

int main(int argc, char **argv) {
   char Buffer[128];
   char *ip_address = NULL;
   unsigned short port = DEFAULT_PORT;
   int retval;
   int fromlen;
   int i;
   int socket_type = DEFAULT_PROTO;
   struct sockaddr_in local, from;
   WSADATA wsaData;
   SOCKET listen_socket, msgsock;

   /* Parse arguments, if there are arguments supplied */
   if (argc > 1) {
       for (i = 1; i < argc; i++) {
           // switches or options...
           if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
               // Change to lower...if any
               switch (tolower(argv[i][1])) {
                       // if -p or /p
                   case 'p':
                       if (!stricmp(argv[i + 1], "TCP"))
                           socket_type = SOCK_STREAM;
                       else if (!stricmp(argv[i + 1], "UDP"))
                           socket_type = SOCK_DGRAM;
                       else
                           Usage(argv[0]);
                       i++;
                       break;
                       // if -i or /i, for server it is not so useful...
                   case 'i':
                       ip_address = argv[++i];
                       break;
                       // if -e or /e
                   case 'e':
                       port = atoi(argv[++i]);
                       break;
                       // No match...
                   default:
                       Usage(argv[0]);
                       break;
               }
           } else
               Usage(argv[0]);
       }
   }

   // Request Winsock version 2.2
   if ((retval = WSAStartup(0x202, &wsaData)) != 0) {
       fprintf(stderr, "Server: WSAStartup() failed with error %d\n", retval);
       WSACleanup();
       return -1;
   } else
       printf("Server: WSAStartup() is OK.\n");

   if (port == 0) {
       Usage(argv[0]);
   }

   local.sin_family = AF_INET;
   local.sin_addr.s_addr = (!ip_address) ? INADDR_ANY : inet_addr(ip_address);

   /* Port MUST be in Network Byte Order */
   local.sin_port = htons(port);
   // TCP socket
   listen_socket = socket(AF_INET, socket_type, 0);

   if (listen_socket == INVALID_SOCKET) {
       fprintf(stderr, "Server: socket() failed with error %d\n", WSAGetLastError());
       WSACleanup();
       return -1;
   } else
       printf("Server: socket() is OK.\n");

   // bind() associates a local address and port combination with the socket just created.
   // This is most useful when the application is a 
   // server that has a well-known port that clients know about in advance.
   if (bind(listen_socket, (struct sockaddr*) & local, sizeof (local)) == SOCKET_ERROR) {
       fprintf(stderr, "Server: bind() failed with error %d\n", WSAGetLastError());
       WSACleanup();
       return -1;
   } else
       printf("Server: bind() is OK.\n");

   // So far, everything we did was applicable to TCP as well as UDP.
   // However, there are certain steps that do not work when the server is
   // using UDP. We cannot listen() on a UDP socket.
   if (socket_type != SOCK_DGRAM) {
       if (listen(listen_socket, 5) == SOCKET_ERROR) {
           fprintf(stderr, "Server: listen() failed with error %d\n", WSAGetLastError());
           WSACleanup();
           return -1;
       } else
           printf("Server: listen() is OK.\n");
   }
   printf("Server: %s: I'm waiting connection\non port %d, protocol %s\n", argv[0], port, (socket_type == SOCK_STREAM) ? "TCP" : "UDP");

   while (1) {
       fromlen = sizeof (from);
       // accept() doesn't make sense on UDP, since we do not listen()
       if (socket_type != SOCK_DGRAM) {
           msgsock = accept(listen_socket, (struct sockaddr*) & from, &fromlen);
           if (msgsock == INVALID_SOCKET) {
               fprintf(stderr, "Server: accept() error %d\n", WSAGetLastError());
               WSACleanup();
               return -1;
           } else
               printf("Server: accept() is OK.\n");
           printf("Server: accepted connection from %s, port %d\n", inet_ntoa(from.sin_addr), htons(from.sin_port));

       } else
           msgsock = listen_socket;

       // In the case of SOCK_STREAM, the server can do recv() and send() on
       // the accepted socket and then close it.
       // However, for SOCK_DGRAM (UDP), the server will do recvfrom() and sendto()  in a loop.
       if (socket_type != SOCK_DGRAM)
           retval = recv(msgsock, Buffer, sizeof (Buffer), 0);

       else {
           retval = recvfrom(msgsock, Buffer, sizeof (Buffer), 0, (struct sockaddr *) & from, &fromlen);
           printf("Server: Received datagram from %s\n", inet_ntoa(from.sin_addr));
       }

       if (retval == SOCKET_ERROR) {
           fprintf(stderr, "Server: recv() failed: error %d\n", WSAGetLastError());
           closesocket(msgsock);
           continue;
       } else
           printf("Server: recv() is OK.\n");
       if (retval == 0) {
           printf("Server: Client closed connection.\n");
           closesocket(msgsock);
           continue;
       }
       printf("Server: Received %d bytes, data \"%s\" from client\n", retval, Buffer);
       printf("Server: Echoing the same data back to client...\n");
       if (socket_type != SOCK_DGRAM)
           retval = send(msgsock, Buffer, sizeof (Buffer), 0);
       else
           retval = sendto(msgsock, Buffer, sizeof (Buffer), 0, (struct sockaddr *) & from, fromlen);

       if (retval == SOCKET_ERROR) {
           fprintf(stderr, "Server: send() failed: error %d\n", WSAGetLastError());
       } else
           printf("Server: send() is OK.\n");

       if (socket_type != SOCK_DGRAM) {
           printf("Server: I'm waiting more connection, try running the client\n");
           printf("Server: program from the same computer or other computer...\n");
           closesocket(msgsock);
       } else
           printf("Server: UDP server looping back for more requests\n");
       continue;
   }
   return 0;
}

 

 

client

>#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DEFAULT_PORT 2007
// TCP socket type
#define DEFAULT_PROTO SOCK_STREAM 

void Usage(char *progname) {
   fprintf(stderr, "Usage: %s -p [protocol] -n [server name/IP] -e [port_num] -l [iterations]\n", progname);
   fprintf(stderr, "Where:\n\tprotocol is one of TCP or UDP\n");
   fprintf(stderr, "\t- server is the IP address or name of server\n");
   fprintf(stderr, "\t- port_num is the port to listen on\n");
   fprintf(stderr, "\t- iterations is the number of loops to execute.\n");
   fprintf(stderr, "\t- (-l by itself makes client run in an infinite loop,\n");
   fprintf(stderr, "\t- Hit Ctrl-C to terminate it)\n");
   fprintf(stderr, "\t- The defaults are TCP , localhost and 2007\n");
   WSACleanup();
   exit(1);
}

int main(int argc, char **argv) {
   char Buffer[128];
   // default to localhost
   char *server_name = "localhost";
   unsigned short port = DEFAULT_PORT;
   int retval, loopflag = 0;
   int i, loopcount, maxloop = -1;
   unsigned int addr;
   int socket_type = DEFAULT_PROTO;
   struct sockaddr_in server;
   struct hostent *hp;
   WSADATA wsaData;
   SOCKET conn_socket;

   if (argc > 1) {
       for (i = 1; i < argc; i++) {
           if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
               switch (tolower(argv[i][1])) {
                   case 'p':
                       if (!stricmp(argv[i + 1], "TCP"))
                           socket_type = SOCK_STREAM;
                       else if (!stricmp(argv[i + 1], "UDP"))
                           socket_type = SOCK_DGRAM;
                       else
                           Usage(argv[0]);
                       i++;
                       break;
                   case 'n':
                       server_name = argv[++i];
                       break;
                   case 'e':
                       port = atoi(argv[++i]);
                       break;
                   case 'l':
                       loopflag = 1;
                       if (argv[i + 1]) {
                           if (argv[i + 1][0] != '-')
                               maxloop = atoi(argv[i + 1]);
                       } else
                           maxloop = -1;
                       i++;
                       break;
                   default:
                       Usage(argv[0]);
                       break;
               }
           } else
               Usage(argv[0]);
       }
   }

   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");

   if (port == 0) {
       Usage(argv[0]);
   }
   // Attempt to detect if we should call gethostbyname() or gethostbyaddr()
   if (isalpha(server_name[0])) { // server address is a name
       hp = gethostbyname(server_name);
   } else { // Convert nnn.nnn address to a usable one
       addr = inet_addr(server_name);
       hp = gethostbyaddr((char *) & addr, 4, AF_INET);
   }
   if (hp == NULL) {
       fprintf(stderr, "Client: Cannot resolve address \"%s\": Error %d\n", server_name, WSAGetLastError());
       WSACleanup();
       exit(1);
   } else
       printf("Client: gethostbyaddr() is OK.\n");
   // Copy the resolved information into the sockaddr_in structure
   memset(&server, 0, sizeof (server));
   memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
   server.sin_family = hp->h_addrtype;
   server.sin_port = htons(port);

   conn_socket = socket(AF_INET, socket_type, 0); /* Open a socket */
   if (conn_socket < 0) {
       fprintf(stderr, "Client: Error Opening socket: Error %d\n", WSAGetLastError());
       WSACleanup();
       return -1;
   } else
       printf("Client: socket() is OK.\n");

   // Notice that nothing in this code is specific to whether we 
   // are using UDP or TCP.
   // We achieve this by using a simple trick.
   //    When connect() is called on a datagram socket, it does not 
   //    actually establish the connection as a stream (TCP) socket
   //    would. Instead, TCP/IP establishes the remote half of the
   //    (LocalIPAddress, LocalPort, RemoteIP, RemotePort) mapping.
   //    This enables us to use send() and recv() on datagram sockets,
   //    instead of recvfrom() and sendto()
   printf("Client: Client connecting to: %s.\n", hp->h_name);
   if (connect(conn_socket, (struct sockaddr*) & server, sizeof (server)) == SOCKET_ERROR) {
       fprintf(stderr, "Client: connect() failed: %d\n", WSAGetLastError());
       WSACleanup();
       return -1;
   } else
       printf("Client: connect() is OK.\n");

   // Test sending some string
   loopcount = 0;
   while (1) {
       wsprintf(Buffer, "This is a test message from client #%d", loopcount++);
       retval = send(conn_socket, Buffer, sizeof (Buffer), 0);

       if (retval == SOCKET_ERROR) {
           fprintf(stderr, "Client: send() failed: error %d.\n", WSAGetLastError());
           WSACleanup();
           return -1;
       } else
           printf("Client: send() is OK.\n");
       printf("Client: Sent data \"%s\"\n", Buffer);

       retval = recv(conn_socket, Buffer, sizeof (Buffer), 0);
       if (retval == SOCKET_ERROR) {
           fprintf(stderr, "Client: recv() failed: error %d.\n", WSAGetLastError());
           closesocket(conn_socket);
           WSACleanup();
           return -1;
       } else
           printf("Client: recv() is OK.\n");

       // We are not likely to see this with UDP, since there is no
       // 'connection' established.
       if (retval == 0) {
           printf("Client: Server closed connection.\n");
           closesocket(conn_socket);
           WSACleanup();
           return -1;
       }

       printf("Client: Received %d bytes, data \"%s\" from server.\n", retval, Buffer);
       if (!loopflag) {
           printf("Client: Terminating connection...\n");
           break;
       } else {
           if ((loopcount >= maxloop) && (maxloop > 0))
               break;
       }
   }
   closesocket(conn_socket);
   WSACleanup();

   return 0;
}

 

για να τρέξουν χρειάζεται να συμπεριλάβετε και τη library ws2_32.lib

Ευχαριστώ

  • Απαντ. 30
  • Δημ.
  • Τελ. απάντηση
Δημοσ.

Προσπαθησε να φτιαξεις ενα chat προγραμμα, για να καταλαβεις τι παιζει. Με τα πολλα μπλα μπλα δε θα καταφερεις και τιποτα, εξασκηση θελει. ;)

Δημοσ.

Με παρακολουθείς ρε και κάνεις τον έξυπνο..!!? Αυτό ακριβως προσπαθώ να φτιάξω από χθες αλλά επειδή είδα και απόειδα είπα να ρωτήσω κάποιον που τα έχει ξαναδεί...!

αν έχεις ασχοληθεί απάντα αν έχεις χρόνο σε αυτα που ρώτησα!

Δημοσ.

Η διαδικασία της εξυπηρέτησης και γενικότερα του πρωτοκόλου επικοινωνίας ενός client με ένα server είναι καθαρά θέμα υλοποίησης και μόνο. Στην δικιά σου περίπτωση συμβαίνουν τα εξής:

 

1.) Ο server εξυπηρετεί έναν client τη φορά με αποτέλεσμα οι υπόλοιποι πιθάνοι clients να περιμένουν μέχρι να τελειώσει ο server:

 

 

>
while (1) {
       fromlen = sizeof (from);
       // accept() doesn't make sense on UDP, since we do not listen()
       if (socket_type != SOCK_DGRAM) {
           msgsock = accept(listen_socket, (struct sockaddr*) & from, &fromlen);
           if (msgsock == INVALID_SOCKET) {
               fprintf(stderr, "Server: accept() error %d\n", WSAGetLastError());
               WSACleanup();
               return -1;
           } else
               printf("Server: accept() is OK.\n");
           printf("Server: accepted connection from %s, port %d\n", inet_ntoa(from.sin_addr), htons(from.sin_port));

       } else
           msgsock = listen_socket;

   ....
}

 

 

2.) Όταν συνδεθεί ένας client αυτό που στην ούσια γίνεται έιναι ένα ping-pong ενός string:

a.) Client

 

>
       retval = send(conn_socket, Buffer, sizeof (Buffer), 0);
....
       retval = recv(conn_socket, Buffer, sizeof (Buffer), 0);

 

 

b.) Client

 

 

>
       if (socket_type != SOCK_DGRAM)
           retval = recv(msgsock, Buffer, sizeof (Buffer), 0);

       else {
           retval = recvfrom(msgsock, Buffer, sizeof (Buffer), 0, (struct sockaddr *) & from, &fromlen);
           printf("Server: Received datagram from %s\n", inet_ntoa(from.sin_addr));
       }
....
       if (socket_type != SOCK_DGRAM)
           retval = send(msgsock, Buffer, sizeof (Buffer), 0);
       else
           retval = sendto(msgsock, Buffer, sizeof (Buffer), 0, (struct sockaddr *) & from, fromlen);

 

 

3.) Όταν τελειώσει ο server με τον client κλείνει την σύνδεση και περιμένει νέες συνδέσεις:

 

 

>
       if (socket_type != SOCK_DGRAM) {
           printf("Server: I'm waiting more connection, try running the client\n");
           printf("Server: program from the same computer or other computer...\n");
           closesocket(msgsock);
       } else
           printf("Server: UDP server looping back for more requests\n");
       continue;
   }

 

 

4.) Απο την άλλη πλευρά ο client θα συνεχίσει να νομίζει ότι είναι συνδεδεμένος με τον server και θα συνεχίσει να του στέλνει μηνύματα, όχι για πολύ βέβαια γιατί θα πάρει errors, οπότε τελικά θα τερματίσει και αυτός. Εκτός μόνο αν το flag (-l ) το ακολουθεί ο άσσος (1) ή παραλειφθεί εντελώς, τότε μετά το πρώτο loop θα τερματίσει και αυτός!

Δημοσ.

Σχεδόν όπως το είχα καταλάβει.. ευχαριστώ..

 

Από τη στιγμή που εξηπηρετηθεί πχ ο πρώτος client μετά συνδέεται ο δεύτερος αλλά στην ίδια μεταβλητή socket άρα δεν μπορούμε να αναφερθούμε ξανά στον πρώτο έτσι δεν είναι..? Άρα πώς θα μπορέσω να διαχειρίζομαι περισσότερους clients.. με πίνακα socket μεταβλητής..??

Και πάλι έτσι θα έχω το πρόβλημα ότι μέχρι να εξυπηρετηθεί ένας client οι άλλοι θα περιμένουν..

Δημοσ.

Για να μπορεί ο server να εξυπηρετεί παραπάνω απο έναν client τη φορά, ταυτόχρονα, πρέπει κάθε φορά που συνδέεται ένας client, να δημιουργείται μια υπο-διεργασία (sub-process, thread, Process and Thread Functions) που θα εξυπηρετεί τον client και θα ελευθερώνει τον "κύριο" server για να μπορεί να ακούει/εξυπηρετήσει και άλλους

Δημοσ.
Για να μπορεί ο server να εξυπηρετεί παραπάνω απο έναν client τη φορά, ταυτόχρονα, πρέπει κάθε φορά που συνδέεται ένας client, να δημιουργείται μια υπο-διεργασία (sub-process, thread, Process and Thread Functions) που θα εξυπηρετεί τον client και θα ελευθερώνει τον "κύριο" server για να μπορεί να ακούει/εξυπηρετήσει και άλλους

 

Αυτό ακριβώς ήθελα να ακούσω...!! (Στην πραγματικότητα αυτός ο τρόπος χρησιμοποιείται..?)

 

 

WSAAsyncSelect Καλη τυχη

 

Κάτι έχει πάρει το αυτί μου για το θέμα αλλά όπως είπα είμαι νέος και και δεν την έχω ψάξει τη συγκεκριμένη συνάρτηση... Θα το κοιτάξω σήμερα και αν εχω απορείες σε αυτό αλλά και γενικότερα θα ποστάρω εδώ..

 

---------- Το μήνυμα προστέθηκε στις 14:17 ----------

 

Απ ότι κατάλαβα ένα πρόβλημα θα είναι η fork() η οποία δεν υπάρχει στα Microsoftowindows και έχω τρεις επιλογές... ή να βάλω Linux ή να μάθω πώς λειτουργούν οι εντολές για threads στα windows ή να χρησιμοποιήσω το cygwin που την προσομοιώνει αλλά θα χάσω(έστω και λίγο) σε ταχύτητα..

 

Δεν πιστεύω να υπάρχει καμιά άλλη λύση και να μην την ξέρω..?

μάλλον με βλέπω για cygwin να ξεμπερδευω.. τι λέτε..?

Δημοσ.

Στο Linux η fork σου λύνει τα χέρια σε τέτοιες περιπτώσεις, απλά και εύκολα. Δεν νομίζω όμως ότι και στα windows είναι πολύ δύσκολο. Με ένα προχειρο search μπορείς να βρείς πολλά παραδείγματα χωρίς να χρειάζεται να εμβαθύνεις πολύ στα windows threads:

http://www.codersource.net/win32_multithreading.html

Δημοσ.

Τελικά χρησιμοποιώ προς το παρόν το cygwin και τη fork().

 

Τώρα τι τρόποι υπάρχουν για να περάσω δεδομένα απο τον πατέρα στο παιδί και αντίθετα..?

πχ θέλω να έχω έναν πίνακα Α που καθώς ενημερώνεται από τον πατέρα να ενημερώνεται και ο αντίστοιχος στο παιδί ή παιδία...

ευχαριστώ για το χρόνο σας..

Δημοσ.
Τώρα τι τρόποι υπάρχουν για να περάσω δεδομένα απο τον πατέρα στο παιδί και αντίθετα..?

 

Κοινή μνήμη..(?)

 

ps: Project με client-server και δεν σας είπανε ρητώς να το κάνετε σε unix-like system?

fork, shared memory, semaphores κλτ...

Δημοσ.

Έχεις καμιά ιδέα για το πώς θα το κάνω αυτό..? Δοκίμασα να περάσω στην διαδικασία παιδί τη διεύθυνση του πίνακα αλλά δεν δούλεψε... δεν θα έπρεπε να δουλεύει κάτι τέτοιο..??

 

Όχι δε μας είπαν να το κάνουμε σε unix.. μας είπαν όπου μας βολεύει..! Και δεν είναι για τη σχολή.. για μένα και για εξάσκηση προσπαθώ να φτιάξω ένα προγραμματάκι πάνω σε αυτά που κάνουμε στη σχολή..

Δημοσ.
Τελικά χρησιμοποιώ προς το παρόν το cygwin και τη fork().

 

Τώρα τι τρόποι υπάρχουν για να περάσω δεδομένα απο τον πατέρα στο παιδί και αντίθετα..?

πχ θέλω να έχω έναν πίνακα Α που καθώς ενημερώνεται από τον πατέρα να ενημερώνεται και ο αντίστοιχος στο παιδί ή παιδία...

ευχαριστώ για το χρόνο σας..

 

Η απλή λύση είναι η pipe()

 

fork() and pipe() -- you have the power

 

αλλά αν ρωτάς εμένα για ποιό λόγο χρειάζεται το παιδί να γνωρίζει οτιδήποτε για τον πατέρα σε ένα τέτοιο πρόγραμμα;

 

απλά κάνεις fork() και το παιδί χειρίζεται την επικοινωνία και ο μπαμπάς ξανα-ακούει για νέες συνδέσεις...

Δημοσ.
Η απλή λύση είναι η pipe()

 

fork() and pipe() -- you have the power

 

αλλά αν ρωτάς εμένα για ποιό λόγο χρειάζεται το παιδί να γνωρίζει οτιδήποτε για τον πατέρα σε ένα τέτοιο πρόγραμμα;

 

απλά κάνεις fork() και το παιδί χειρίζεται την επικοινωνία και ο μπαμπάς ξανα-ακούει για νέες συνδέσεις...

 

 

Θέλω να περάσω έναν πίνακα βασικά σε κάθε παιδί που θα διαχειρίζεται τον καθένα 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);
   }
}

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...