Two-way communication in TCP: server-client implementation

  • I have written some code to establish a client and server. I have managed to get a one way communication from client to server. I have added the code below. Can someone please have a look and see it is the right way to do it? If this is good enough, how can I get two communication to work now?



    Client:



    #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;
    }

    what i meant to ask if my code was the right way to establish one way communication?? my more specific ques is how can i establsih 2-way (duplex communication)?

    and thnx for the link!!

    Checkout "A Sample GNU/Linux Application" chapter from "Advanced Linux Programming" book. In this chapter you can find good practices for two-way communication since a simple HTTP web server is implemented.

  • You can do a two way data transfer here. I have modified your code to show that. Now the
    server is echoing back to the client the same string which it has received. Now the client
    displays the same string, which it receives from the server. Pl. experiment with this.



    client main loop



        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 main loop



        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

    thank you. i will test it out!! so this 2way communication is sufficient to be considered as chat messaging btw two machines???

    Since you are using TCP, this is having some limitations. TCP is a byte oriented protocol. So ideally you cannot expect to get all the data in a single "recv". You need to run recv in loop even to grab all the data in a line, if the line is arbitrarily large. Anyway this code should work for normal user inputs, which may not be that large. I would suggest, you may also try implementing this using UDP.Also pl. read from the link , http://www.faqs.org/faqs/unix-faq/socket/ to learn more about sockets or from any good book like "Network Programming" byStevens.Pl. let me know if the code worked.

    nope, it is not working!!client is able to send message which server receives, but after that nothing happens!!

    I missed the send function in the server side , which I have updated.The character array buffer is populated by the recv function and the same array "buffer" is used to send data.I hope you are not using the "buff" as was there in your orginal code.

    hey, i made a mistake!! ur modifications worked!! but now i want to implement a continuous 2 way communication whereby a server can also send messages to the client, can u help me how? i cannot find much on google also, how do i check in recv function if all the data has been actually received?? thnx again for ur help!!

    If you want server to send messages to the client.. simply add a fgets after the server's recv (as you did in client) and then use send.In your current code the problem will be, this becomes an iterative server, which can server only a single client at one point of time. That means finally you need to implement a concurrent server using threads/fork.For the second question, how to know that you have received all the data using recv->when recv returns 0, but this is possible only when the other side closes connection (this will not work for you) or send number of data, before sending data.

    another problem is that this isnt full duplex. do i need to implement full duplex using threads??? and to handle multiple clients, i need to use fork()??

    yes, you can do it in that way.

    hey Tanmoy, i managed to get full duplex to work using fork(). what else can i try now to expand on sockets programming?? wud really appreciate some guidance here

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM

Tags used