问题
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