0

I've wrote a simple client code in python, and I'm trying to connect to a simple echo server written in C.

I know it shouldn't matter, but for some reason I did manage to connect to a server written in python, but I cannot connect to the C server.

Here's the code of the client:

import socket
import sys
import time

HOST = 'localhost'   
PORT = 11000             
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
msg = raw_input()
s.send(msg)
data = s.recv(len(msg))
s.close()
print 'Received: ', data

And here's the C code of the echo server:

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

#ifndef AF_INET
#define AF_INET 2
#endif

#ifndef SOCK_DGRAM
#define SOCK_DGRAM 2
#endif

#ifndef INADDR_ANY
#define INADDR_ANY 0
#endif

#ifndef IP_DONTFRAG
#define IP_DONTFRAG     67
#endif

#define BUFFER_SIZE 1024

#define ECHO_PORT_UDP 10000
#define ECHO_PORT_TCP 11000

int main(int argc, char *argv[]) {
    int echo_socket = 0;
    int echo_socket_child = 0; // for TCP
    struct sockaddr_in server;
    struct sockaddr_in client;
    struct hostent *hostp; // client host info
    struct sockaddr_in clientaddr; // client addr
    char *hostaddrp; // dotted decimal host addr string
    char buffer[BUFFER_SIZE];
    unsigned int clientlen = 0;
    unsigned int serverlen = 0;
    int received = 0;
    int port = 0;
    char *endptr;
    int optval = 1;
    int msg_byte_size = 0;


// Parameters check
    if (argc == 2) {
        port = strtol(argv[1], &endptr, 0);
        if ((*endptr) || ((port != ECHO_PORT_UDP) && (port != ECHO_PORT_TCP)))  {
        printf("EchoServer: Invalid port number.\n Use port %d for UDP, port %d for TCP.\n", ECHO_PORT_UDP, ECHO_PORT_TCP);
            return -1;
        }
        else {
            if (port == ECHO_PORT_UDP) {
                printf("EchoServer: Running UDP on port %d.\n", port);
            }
            if (port == ECHO_PORT_TCP) {
                printf("EchoServer: Running TCP on port %d.\n", port);
            }
        }
    }
    else {
        printf("EchoServer: Invalid arguments.\n");
        return -1;
    }


// Opening UDP socket
    if (port == ECHO_PORT_UDP) {
        if ((echo_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
            printf("EchoServer: Failed opening socket");
            return -1;
        }

    }
    if (port == ECHO_PORT_TCP) {
        if ((echo_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
            printf("EchoServer: Failed opening socket");
            return -1;
        }

        // setsockopt: Handy debugging trick that lets  us rerun the server immediately after we kill it; otherwise we have to wait about 20 secs.
        // Eliminates "ERROR on binding: Address already in use" error.
        setsockopt(echo_socket, SOL_SOCKET, SO_REUSEADDR,(const void *)&optval , sizeof(int));

    }

// Construct the server sockaddr_in structure
    memset(&server, 0, sizeof(server));             /* Clear struct */
    server.sin_family = AF_INET;                    /* Internet/IP */
    server.sin_addr.s_addr = htonl(INADDR_ANY);     /* Any IP address */
    server.sin_port = htons(atol(argv[1]));         /* server port */

// Bind the socket
    serverlen = sizeof(server);
    if (bind(echo_socket, (struct sockaddr *) &server, serverlen) < 0) {
        printf("EchoServer: Failed binding socket");
        return -1;
}    


// Wait for a datagram until cancelled
if (port == ECHO_PORT_UDP) {
    while (1) {
        /* Receive a message from the client */
        clientlen = sizeof(client);
        if ((received = recvfrom(echo_socket, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &clientlen)) < 0) {

            printf("EchoServer: Failed receiving datagram");
            return -1;
        }
        printf("Client datagram received from: %s\n", inet_ntoa(client.sin_addr));
        /* Send the message back to client */
        if (sendto(echo_socket, buffer, received, 0, (struct sockaddr *) &client, sizeof(client)) != received) {
            printf("Mismatch in number of echoed bytes");
            return -1;
        }
    }
}

// Wait for a connection until cancelled
if (port == ECHO_PORT_TCP) {
    while (1) {
        echo_socket_child = accept(echo_socket, (struct sockaddr *) &client, &clientlen);
        if (echo_socket_child < 0) {
            printf("ERROR on accept");
            break;
        }

        // gethostbyaddr: determine who sent the message
        hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr, sizeof(clientaddr.sin_addr.s_addr), AF_INET);
        if (hostp == NULL) {
            printf("ERROR on gethostbyaddr");
            break;
        }
        hostaddrp = inet_ntoa(clientaddr.sin_addr);
        if (hostaddrp == NULL) {
            printf("ERROR on inet_ntoa\n");
            break;
        }
        printf("server established connection with %s \n", hostaddrp);

        // read: read input string from the client
        bzero(buffer, BUFFER_SIZE);
        msg_byte_size = read(echo_socket_child, buffer, BUFFER_SIZE);
        if (msg_byte_size < 0) {
            printf("ERROR reading from socket");
            break;
        }
        printf("server received %d bytes: %s", msg_byte_size, buffer);

        // write: echo the input string back to the client
        msg_byte_size = write(echo_socket_child, buffer, strlen(buffer));
        if (msg_byte_size < 0) {
            printf("ERROR writing to socket");
            break;
        }
    } // endof while(1)
    close(echo_socket_child);
    return -1;
}
return 0;

}

Any ideas why I fail to connect to the server?

edit: this is the error I receive:

Traceback (most recent call last):
  File "s.py", line 8, in <module>
    s.connect((HOST, PORT))
  File "C:\Python27\lib\socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 10061]
6
  • Why are you defining all those constants? Commented Nov 25, 2013 at 16:28
  • I did not write this server, but rather use it as a black box. Commented Nov 25, 2013 at 16:30
  • What is the python client reporting as to why it fails to connect? Commented Nov 25, 2013 at 16:34
  • Once you're running the server, does it show up as listening under netstat -a? If not, I would debug the c++ until it does. Commented Nov 25, 2013 at 16:43
  • Nope, I really don't see anything from port 11000 which is listening at all.. do you see problems in the server? Commented Nov 25, 2013 at 16:49

1 Answer 1

0

(1) Add a listen call to the TCP section of the code.

(2) You have to tell accept what the length of the sockaddr you are passing it is and it will in return tell you the length of the address of the client it returned. You were passing it as 0 length so naturally it didn't pass back a client address which subsequently makes your gethostbyaddr fail with unknown address.

(3) If you don't close the client socket within the loop it just remains open (and leaks a file descriptor) for the duration of the server's life. Eventually you will run out of FDs. It doesn't effect your client which just closes after the receipt of one msg but any client who writes more than one message will never have it received by the server and will never receive an eof from the server.

if (port == ECHO_PORT_TCP)
{
    if (listen(echo_socket, ECHO_PORT_TCP) == -1)
    {
        perror("listen");
        exit(1);
    }

    while (1)
    {
        clientlen = sizeof(client);

        echo_socket_child = accept(echo_socket, (struct sockaddr *) &client, &clientlen);

        if (echo_socket_child < 0)
        {
              perror("accept"); 
              break; 
        }

        // gethostbyaddr: determine who sent the message
        hostp = gethostbyaddr((const char *) &client.sin_addr.s_addr, sizeof(client.sin_addr.s_addr), AF_INET);

        if (hostp == NULL)
        {   herror("byaddr"); 
            break;
        }

        hostaddrp = inet_ntoa(client.sin_addr);

        if (hostaddrp == NULL)
        {
            printf("ERROR on inet_ntoa\n");
            break;
        }

        printf("server established connection with %s (%s)\n", hostp->h_name, hostaddrp);

        bzero(buffer, BUFFER_SIZE);
        msg_byte_size = read(echo_socket_child, buffer, BUFFER_SIZE);

        if (msg_byte_size < 0)
        {
            printf("ERROR reading from socket");
            break;
        }

        printf("server received %d bytes: %s", msg_byte_size, buffer);

        msg_byte_size = write(echo_socket_child, buffer, strlen(buffer));

        if (msg_byte_size < 0)
        {
            printf("ERROR writing to socket");
            break;
        }

        close(echo_socket_child);

    } // endof while(1)

    return -1;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Ok, after adding the listening part in the server I reach to the point where I send the message, but after sending a message it crushes both on client and server. error in client: Traceback (most recent call last): File "s.py", line 11, in <module> data = s.recv(len(msg)) socket.error: [Errno 10054] And error on server: ERROR on gethostbyaddr P.S why to add a close inside the loop, and not leave it outside?
@Jjang, I amended my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.