I'm working on a lab project that requires me to write a TCP client in C and a TCP server in Python.
The issue I'm having right now with the TCP client is that every time I try to connect the client to the server which is also running on my PC, there is a "Connection refused" error and the errno
is 111. (The TCP server works just fine since every time I type in localhost:5566
on web browser, the server received some information)
By the way, I'm running all the code on a virtual machine with Ubuntu 18.04.6 installed.
The C code for the client and the Python code for the server is attached.
TCP client code (in C)
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#define SERVER_IP "127.0.0.1" /* Dotted-decimal representation of server's IP address */
#define SERVER_PORT 5566 /* Server's port number */
#define BUF_SIZE 1024 /* Size of buffer used for data transmission */
static int client_fd; /* Client socket file descriptor */
static struct sockaddr_in server_addr; /* Server socket address struct */
static void client_init() {
/* Creates a client socket descriptor */
client_fd = socket(AF_INET, SOCK_STREAM, 0);
/* Handles socket error */
if (client_fd == -1) {
perror("socket error");
exit(errno);
}
/* Sets fields of Server socket address struct */
server_addr.sin_family = AF_INET; /* Protocol family (IPv4) */
server_addr.sin_port = SERVER_PORT; /* Port number in network byte order (big-endian) */
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); /* IP address in network byte order (big-endian) */
/* Establishes a connection to the server and handles connect error */
if (connect(client_fd, (struct sockaddr *)(&server_addr), sizeof(server_addr)) == -1) {
perror("connect error");
exit(errno);
}
}
void main() {
FILE *file;
char buffer[BUF_SIZE];
file = fopen("./client.txt", "r+");
if (file == NULL) {
perror("fopen error");
exit(errno);
}
client_init();
while (fgets(buffer, BUF_SIZE, file) != NULL) {
// Sends data to the server and handles sendto error
if (sendto(client_fd, buffer, BUF_SIZE, 0, (struct sockaddr *)(&server_addr), sizeof(server_addr))== -1) {
perror("sendto error");
exit(1);
}
// Clears buffer
bzero(buffer, BUF_SIZE);
}
fclose(file);
}
TCP server code (in Python)
import socket
import threading
SERVER_IP = "127.0.0.1"
SERVER_PORT = 5566
SERVER_ADDR = (SERVER_IP, SERVER_PORT)
PACKET_SIZE = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(SERVER_ADDR)
def client_handler(client, client_addr):
print(f"[NEW CONNECTION] {client_addr}\n")
while True:
# Reads at most PACKET_SIZE bytes data, blocks when no packet is received
packet = client.recv(PACKET_SIZE)
# Writes file from the packet received
with open('./server.txt', 'wb') as file:
file.write(packet)
def server_init():
print(f"Listening on {SERVER_PORT}")
server.listen()
while True:
# Everytime a new client is connected to the server, create a new thread dedicated to that client
# Every thread will block until the connection to that client is established
client, client_addr = server.accept()
thread = threading.Thread(target=client_handler, args=(client, client_addr))
thread.start()
print(f"[ACTIVE CONNECTION] {threading.active_count() - 1}\n")
print("Starting server...")
server_init()
All Unix-style socket networking code uses what is known as "network byte order", which is also known as "big-endian". But many common desktop/embedded platforms (e.g. x86 and ARM) use "little-endian" byte ordering.
When you set up a socket in your C code, you need to convert your port number from the native, little-endian, "host" byte order, to "network" order. To do that, you can use the htons() function, which is a shortening of host-to-network-short().
i.e. you want this:
server_addr.sin_port = htons(SERVER_PORT);
It seems that the python sockets library handles this kind of thing under the hood, so you don't need to worry about it there.