Server and client in Python and C

萝らか妹 提交于 2020-01-06 06:52:34

问题


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]

回答1:


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


来源:https://stackoverflow.com/questions/20198003/server-and-client-in-python-and-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!