Search code examples
csocketstcpnetwork-programming

Why is TCP server receiving corrupted messages?


I'm trying to set up TCP/UDP server hosting on the same port.

UDP part is working fine but TCP part doesn't receive messages properly.

I tried testing it with netcat eg. when I send "TCP y u do dis" it outputs something like "D(" and keeps spinning in do while loop.

    //Creating TCP listen socket
    tcp_listenfd=socket(AF_INET, SOCK_STREAM, 0);
    bzero(&tcp_servaddr, sizeof(tcp_servaddr));
    tcp_servaddr.sin_family=AF_INET;
    tcp_servaddr.sin_port=htons(atoi(tcp_port));
    tcp_servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

    //Binding TCP socket
    setsockopt(tcp_listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    bind(tcp_listenfd,(struct sockaddr*)&tcp_servaddr,sizeof(tcp_servaddr));
    listen(tcp_listenfd, 10);

    //Creating UDP listen socket
    udp_listenfd=socket(AF_INET, SOCK_DGRAM, 0);
    bzero(&udp_servaddr, sizeof(udp_servaddr));
    udp_servaddr.sin_family=AF_INET;
    udp_servaddr.sin_port=htons(atoi(udp_port));
    udp_servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

    //Binding UDP listen socket
    bind(udp_listenfd, (struct sockaddr*)&udp_servaddr, sizeof(udp_servaddr));

    //Clear descriptor set
    FD_ZERO(&rset);

    //Max file descriptor
    maxfd = max(tcp_listenfd, udp_listenfd)+1;

    while(1){
        // set listenfd and udpfd in readset
        FD_SET(tcp_listenfd, &rset);
        FD_SET(udp_listenfd, &rset);

        nready = select(maxfd, &rset, NULL, NULL, NULL);

        if (FD_ISSET(tcp_listenfd, &rset)) {
            printf("TCP ready!\n");
            len=sizeof(cli_addr);
            connfd = accept(tcp_listenfd, (struct sockaddr*)&cli_addr, &len);
            do {
                numbytes=recv(tcp_listenfd, tcp_buff, sizeof(tcp_buff), 0);
                printf("Received message: %s\n", tcp_buff);
            }while(strcmp(tcp_buff, "HELLO\n")!=0);
            send(tcp_listenfd, payload, strlen(payload)+1, 0);
            close(connfd);
            bzero(&cli_addr, sizeof(cli_addr));
        }

        if(FD_ISSET(udp_listenfd, &rset)){
            printf("UDP ready!\n");
            len=sizeof(cli_addr);
            do{
                recvfrom(udp_listenfd, udp_buff, 1024, 0,(struct sockaddr *)&cli_addr, &len);
            }while(strcmp(udp_buff, "HELLO\n")!=0);
            sendto(udp_listenfd, payload, strlen(payload)+1, 0, (struct sockaddr *)&cli_addr, len);
            close(udp_listenfd);
            bzero(&cli_addr, sizeof(cli_addr));
        }
    }

Solution

  • Okay, the problem is here:

     connfd = accept(tcp_listenfd, (struct sockaddr*)&cli_addr, &len);
     do {
        numbytes=recv(tcp_listenfd, tcp_buff, sizeof(tcp_buff), 0);
    

    In your recv() call you are passing in tcp_listenfd when you should be passing in connfd instead. (Also you should be checking the return values of all function calls to make sure that the function succeeded, and taking appropriate action (such as printing an error message via perror()) if the function calls failed. See the man page for each function for details about what return-values constitute success vs failure for that function)