クライアントサーバープログラムを作成しています。サーバーはクライアントに数値の範囲を送信し、クライアントはその範囲に対して操作を行い (完全な数値を見つけます)、結果を返します。サーバーは Python で、クライアントは C で記述されています。私のコードは次のとおりです。
サーバー (パイソン):
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()
クライアント (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);
}
プログラムは最初の実行では問題なく動作しますが、2 回または数回実行すると、サーバーは次のような例外をスローしsocket.error: [Errno 111] Connection refused
ます。接続を適切に閉じていないのではないかと感じていますが、何が間違っているのかわかりません。どんな助けでも大歓迎です。