Wechselseitige Kommunikation in TCP: Server-Client-Implementierung

106473
ueg1990

Ich habe Code geschrieben, um einen Client und einen Server einzurichten. Es ist mir gelungen, eine einfache Kommunikation von Client zu Server zu erhalten. Ich habe den Code unten hinzugefügt. Kann jemand bitte sehen und sehen, dass es der richtige Weg ist, es zu tun? Wenn dies gut genug ist, wie kann ich jetzt zwei Kommunikationen zur Arbeit bringen?

Klient:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 3490
#define MAXSIZE 1024

int main(int argc, char *argv[])
{
    struct sockaddr_in server_info;
    struct hostent *he;
    int socket_fd,num;
    char buffer[1024];

    char buff[1024];

    if (argc != 2) {
        fprintf(stderr, "Usage: client hostname\n");
        exit(1);
    }

    if ((he = gethostbyname(argv[1]))==NULL) {
        fprintf(stderr, "Cannot get host name\n");
        exit(1);
    }

    if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== -1) {
        fprintf(stderr, "Socket Failure!!\n");
        exit(1);
    }

    memset(&server_info, 0, sizeof(server_info));
    server_info.sin_family = AF_INET;
    server_info.sin_port = htons(PORT);
    server_info.sin_addr = *((struct in_addr *)he->h_addr);
    if (connect(socket_fd, (struct sockaddr *)&server_info, sizeof(struct sockaddr))<0) {
        //fprintf(stderr, "Connection Failure\n");
        perror("connect");
        exit(1);
    }

    //buffer = "Hello World!! Lets have fun\n";
    //memset(buffer, 0, sizeof(buffer));
    while(1) {
        fgets(buffer,MAXSIZE-1,stdin);
        if ((send(socket_fd,buffer, strlen(buffer),0))== -1) {
            fprintf(stderr, "Failure Sending Message\n");
            close(socket_fd);
            exit(1);
        }
        else {
            printf("Message being sent: %s\n",buffer);
        }
    }   

    /*if ((num = recv(socket_fd, buff, 1024,0))== -1) {
            //fprintf(stderr,"Error in receiving message!!\n");
            perror("recv");
            exit(1);
        }   
    //  num = recv(client_fd, buffer, sizeof(buffer),0);
    buff[num] = '\0';
    printf("Message received: %s\nNumber of bytes received: %d\n", buff,num);*/
    close(socket_fd);   

}

Server:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 3490
#define BACKLOG 10

int main()
{
    struct sockaddr_in server;
    struct sockaddr_in dest;
    int status,socket_fd, client_fd,num;
    socklen_t size;

    char buffer[10241];
    char *buff;
//  memset(buffer,0,sizeof(buffer));
    int yes =1;



    if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== -1) {
        fprintf(stderr, "Socket failure!!\n");
        exit(1);
    }

    if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }
    memset(&server, 0, sizeof(server));
    memset(&dest,0,sizeof(dest));
    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    server.sin_addr.s_addr = INADDR_ANY; 
    if ((bind(socket_fd, (struct sockaddr *)&server, sizeof(struct sockaddr )))== -1)    { //sizeof(struct sockaddr) 
        fprintf(stderr, "Binding Failure\n");
        exit(1);
    }

    if ((listen(socket_fd, BACKLOG))== -1){
        fprintf(stderr, "Listening Failure\n");
        exit(1);
    }

    while(1) {
        size = sizeof(struct sockaddr_in);  

        if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size))==-1) {
            //fprintf(stderr,"Accept Failure\n");
            perror("accept");
            exit(1);
        }
        printf("Server got connection from client %s\n", inet_ntoa(dest.sin_addr));
        //buffer = "Hello World!! I am networking!!\n";

        while(1) {
        if ((num = recv(client_fd, buffer, 10240,0))== -1) {
            //fprintf(stderr,"Error in receiving message!!\n");
            perror("recv");
            exit(1);
        }   
        else if (num == 0) {
            printf("Connection closed\n");
            return 0;
        }
    //  num = recv(client_fd, buffer, sizeof(buffer),0);
        buffer[num] = '\0';
        printf("Message received: %s\n", buffer);
        }

    /*  buff = "I am communicating with the client!!\n";

        if ((send(client_fd,buff, strlen(buff),0))== -1) {
        fprintf(stderr, "Failure Sending Message\n");
        close(client_fd);
        exit(1);
    }
    else {
        printf("Message being sent: %s\nNumber of bytes sent: %d\n",buff, strlen(buff));
    }*/

        close(client_fd);   
        close(socket_fd);   
        //return 0;
    }
    //close(client_fd); 
    return 0;
}
Antworten
8
was wollte ich fragen, ob mein Code der richtige Weg ist, um die Kommunikation in eine Richtung herzustellen? meine spezifischere Frage ist, wie kann ich eine 2-Wege-Kommunikation (Duplex-Kommunikation) einrichten? ueg1990 vor 7 Jahren 0
und danke für den Link !! ueg1990 vor 7 Jahren 0
Das Kapitel "Eine Beispiel-GNU / Linux-Anwendung" aus dem Buch "[Advanced Linux Programming] (http://www.advancedlinuxprogramming.com/alp-folder/)" wird überprüft. In diesem Kapitel finden Sie bewährte Methoden für die bidirektionale Kommunikation, da ein einfacher HTTP-Webserver implementiert ist. vor 6 Jahren 0

1 Antwort auf die Frage

7
Tanmoy Bandyopadhyay

Sie können hier eine bidirektionale Datenübertragung durchführen. Ich habe Ihren Code geändert, um das zu zeigen. Nun sendet der Server die gleiche Zeichenfolge, die er empfangen hat, an den Client zurück. Der Client zeigt jetzt dieselbe Zeichenfolge an, die er vom Server erhält. Pl. experimentiere damit.

Client-Hauptschleife

    while(1) {
        printf("Client: Enter Data for Server:\n");
        fgets(buffer,MAXSIZE-1,stdin);
        if ((send(socket_fd,buffer, strlen(buffer),0))== -1) {
                fprintf(stderr, "Failure Sending Message\n");
                close(socket_fd);
                exit(1);
        }
        else {
                printf("Client:Message being sent: %s\n",buffer);
                num = recv(socket_fd, buffer, sizeof(buffer),0);
                if ( num <= 0 )
                {
                        printf("Either Connection Closed or Error\n");
                        //Break from the While
                        break;
                }

                buff[num] = '\0';
                printf("Client:Message Received From Server -  %s\n",buffer);
           }
    }
    close(socket_fd);

}//End of main

Server-Hauptschleife

    while(1) {

        size = sizeof(struct sockaddr_in);

        if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size))==-1 ) {
            perror("accept");
            exit(1);
        }
        printf("Server got connection from client %s\n", inet_ntoa(dest.sin_addr));

        while(1) {

                if ((num = recv(client_fd, buffer, 1024,0))== -1) {
                        perror("recv");
                        exit(1);
                }
                else if (num == 0) {
                        printf("Connection closed\n");
                        //So I can now wait for another client
                        break;
                }
                buffer[num] = '\0';
                printf("Server:Msg Received %s\n", buffer);
                if ((send(client_fd,buffer, strlen(buffer),0))== -1) 
                {
                     fprintf(stderr, "Failure Sending Message\n");
                     close(client_fd);
                     break;
                }

                printf("Server:Msg being sent: %s\nNumber of bytes sent: %d\n",b
                uffer, strlen(buffer));

        } //End of Inner While...
        //Close Connection Socket
        close(client_fd);
    } //Outer While

    close(socket_fd);
    return 0;
} //End of main
Danke dir. Ich werde es testen !! Diese 2-Wege-Kommunikation reicht also aus, um als Chat-Nachrichten zwischen zwei Maschinen betrachtet zu werden. ueg1990 vor 7 Jahren 0
Da Sie TCP verwenden, hat dies einige Einschränkungen. TCP ist ein byteorientiertes Protokoll. Im Idealfall können Sie also nicht erwarten, alle Daten in einem einzigen "Recv" zu erhalten. Sie müssen recv in loop ausführen, um alle Daten in einer Zeile zu erfassen, wenn die Zeile beliebig groß ist. Auf jeden Fall sollte dieser Code für normale Benutzereingaben funktionieren, die möglicherweise nicht so groß sind. Ich würde vorschlagen, Sie können auch versuchen, dies mit UDP.Also pl zu implementieren. Lesen Sie den Link unter http://www.faqs.org/faqs/unix-faq/socket/, um mehr über Steckdosen oder über ein gutes Buch wie "Network Programming" vonStevens.Pl. zu erfahren. Lassen Sie mich wissen, ob der Code funktioniert hat. Tanmoy Bandyopadhyay vor 7 Jahren 0
Nein, es funktioniert nicht !! Der Client kann eine Nachricht senden, die der Server empfängt, aber danach passiert nichts !! ueg1990 vor 7 Jahren 0
Ich habe die Sendefunktion auf der Serverseite verpasst, die ich aktualisiert habe. Der Zeichenarraypuffer wird von der recv-Funktion aufgefüllt und das gleiche Array "Puffer" wird zum Senden von Daten verwendet. Ich hoffe, Sie verwenden nicht den "Buff", wie er war dort in Ihrem ursprünglichen Code. Tanmoy Bandyopadhyay vor 7 Jahren 0
hey, ich habe einen Fehler gemacht !! Ihre Modifikationen haben funktioniert !! aber jetzt möchte ich eine kontinuierliche 2-Wege-Kommunikation implementieren, bei der ein Server auch Nachrichten an den Client senden kann. Können Sie mir dabei helfen? Ich kann auch nicht viel auf Google finden. Wie kann ich die Recv-Funktion überprüfen, wenn alle Daten tatsächlich empfangen wurden? Danke nochmal für eure Hilfe !! ueg1990 vor 7 Jahren 0
Wenn Sie möchten, dass der Server Nachrichten an den Client sendet, fügen Sie nach dem Recv des Servers (wie in Client) ein Fgets hinzu, und verwenden Sie dann send. Im aktuellen Code wird das Problem ein iterativer Server, der Server kann nur ein einzelner Kunde zu einem bestimmten Zeitpunkt. Das bedeutet, dass Sie schließlich einen Concurrent-Server mit Threads / Fork implementieren müssen. Für die zweite Frage, wie Sie wissen, dass Sie alle Daten mit recv-> erhalten haben, wenn recv 0 zurückgibt, ist dies nur möglich, wenn die andere Seite die Verbindung schließt (Dies funktioniert nicht für Sie) oder senden Sie die Anzahl der Daten, bevor Sie Daten senden. Tanmoy Bandyopadhyay vor 7 Jahren 0
Ein weiteres Problem ist, dass dies nicht Vollduplex ist. muss ich Vollduplex mit Threads implementieren? und um mit mehreren Clients umgehen zu können, muss ich fork () verwenden? ueg1990 vor 7 Jahren 0
ja, das kannst du so machen. Tanmoy Bandyopadhyay vor 7 Jahren 0
Hey Tanmoy, ich habe es geschafft, Full-Duplex mit Hilfe von fork () zu arbeiten. Was kann ich jetzt noch versuchen, die Socket-Programmierung zu erweitern? Wir würden wirklich einige Hinweise hier schätzen ueg1990 vor 7 Jahren 0