Reputation: 7413
I'm creating a client-server program. The server sends the client a range of numbers, the client does an operation on the range (finds perfect numbers) and sends back a result. The server is written in Python and the client in C. Here's my code:
Server (Python):
import socket
def SendRequestToCompute():
# Server-side
SERV_IP = '--some ip--'
# Port
SERV_PORT = --some port--
# Create socket
serv_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serv_socket.connect((SERV_IP, SERV_PORT))
serv_socket.sendall('100')
serv_socket.close()
def ReceiveRequestFromCompute():
# Server-side: all available resources
SERV_IP = ''
SERV_PORT = 2890
# Create and bind the sockets
serv_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Make the socket "reusable" for further tries
serv_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serv_socket.bind((SERV_IP, SERV_PORT))
serv_socket.listen(1)
# Accept the connection and block until a socket is received
client_conn, client_addr = serv_socket.accept()
print 'Connection established: ', client_addr
while 1:
data = client_conn.recv(1024)
# Get the string of numbers
joint_string = repr(data)
# get rid of the ' character at the begining and end caused by repr()
joint_string = joint_string[1:]
return joint_string
# break out of the while loop once all the numbers were recieved
break
if not data: break
client_conn.close()
def SendNumbersToReport(results):
# Server-side
SERV_IP = --some ip--
# port
SERV_PORT = --some port-
# Create socket
serv_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serv_socket.connect((SERV_IP, SERV_PORT))
serv_socket.sendall(results)
data = serv_socket.recv(3)
serv_socket.close()
def main():
print 'Sending a range of numbers to compute to work on.'
# Send a request to compute
SendRequestToCompute()
print 'Waiting to get the results from compute...'
# Receive the results from compute
results = ReceiveRequestFromCompute()
print 'Sending numbers to report to print...'
#Send the numbers to report for printing
SendNumbersToReport(results)
if __name__ == "__main__": main()
Client (C):
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <pthread.h>
#define MAXLINE 4096 /* max text line length */
#define MAXSOCKADDR 128 /* max socket address structure size */
#define BUFFSIZE 8192 /* buffer size for reads and writes */
#define SERV_PORT_REQUEST 2891 /* The port number to get request from compute */
#define SERV_PORT --port number--
#define SERV_IP "--some ip--" /* IP address */
long range = 0;
// The global variable to hold the numbers
char *strnumbers;
// Function prototypes
void *ThreadWorker(void *threadId);
int main(int argc, char **argv){
int i;
int sockfd;
ssize_t n;
struct sockaddr_in cliaddr;
struct sockaddr_in servaddr;
socklen_t clilen;
char sendline[MAXLINE];
char recvline[MAXLINE];
char buffer[MAXLINE];
int listenfd;
pthread_t thread;
void *status;
// Initialize the strnumbers array
strnumbers = (char *) malloc (100 * sizeof(char));
// Get the range of numbers from the server to work on
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT_REQUEST);
// General information for the user
printf("Waiting to recieve a request from the server (manage)...\n");
// Bind the socket and start listening for the peer socket
bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listenfd, 1);
clilen = sizeof(cliaddr);
sockfd = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen);
bzero(buffer, MAXLINE);
if((n = read(sockfd, buffer, MAXLINE)) == 0){
//connection closed by client
close(sockfd);
}else{
// Convert the received range (string) to integer
range = atoi(buffer);
close(sockfd);
}
printf("Request received: Working on %lld numbers.\n", range);
// Create the thread to find the perfect numbers
if((pthread_create(&thread, NULL, ThreadWorker, (void *)0)) != 0){
perror("Failed to create a thread.\n");
exit(-1);
}
// Wait for the thread to finish its job
pthread_join(thread, &status);
// Create the socket to send the the results with
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, SERV_IP, &servaddr.sin_addr);
// Connect to the created socket
if((connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) != 0){
perror("Unable to connect to the server - make sure the server is up and running.");
exit(-1);
}
// Send the numbers via the socket
write(sockfd, strnumbers, 100);
// Close the socket
close(sockfd);
exit(0);
}
void *ThreadWorker(void *threadId)
{
long long total = 0;
long long sum = 0;
long long num;
long long j;
char buffer[30];
// Brute-force algorithm to find the perfect numbers that will take approximately 15 seconds
for(num = 1; num < range; num++){
sum = 0;
for(j = 1; j < num; j++){
if((num % j) == 0){
sum+=j;
}
}
if(sum == num){
// Convert the long number to string
snprintf(buffer, 10, "%lld", sum);
// Concatenate the string to the strnumbers array
strcat(strnumbers, buffer);
// Add a special character at the end of the each number to differentiate each number
strcat(strnumbers, "/");
}
}
pthread_exit(NULL);
}
The program works just fine on the first run, but after running it two or several times, the server throws an exception that says: socket.error: [Errno 111] Connection refused
when trying to send a range of numbers to the client. I have a feeling that maybe I'm not closing the connections appropriately but I can't figure out what I'm doing wrong. Any help would be appreciated.
Upvotes: 3
Views: 1110
Reputation: 84151
You don't need multiple TCP connections between two programs, one is enough since it's full-duplex.
I would suggest that you make your life easier and follow accepted client/server design where server binds its server socket to a known port, listens for client connections, accepts and services them, while clients connect to the known address and port, then send and receive messages over that single TCP connection (according to some application protocol you defined).
Upvotes: 4