3

クライアントサーバープログラムを作成しています。サーバーはクライアントに数値の範囲を送信し、クライアントはその範囲に対して操作を行い (完全な数値を見つけます)、結果を返します。サーバーは 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ます。接続を適切に閉じていないのではないかと感じていますが、何が間違っているのかわかりません。どんな助けでも大歓迎です。

4

1 に答える 1

4

2 つのプログラム間で複数の TCP 接続は必要ありません。全二重なので 1 つあれば十分です。

私はあなたの人生を楽にし、クライアントが既知のアドレスとポートに接続している間、サーバーがそのサーバーソケットを既知のポートにバインドし、クライアント接続をリッスンし、それらを受け入れてサービスする、受け入れられたクライアント/サーバー設計に従うことをお勧めします。その単一のTCP接続を介してメッセージを受信します(定義したアプリケーションプロトコルに従って)。

于 2012-11-29T04:48:23.633 に答える