2012-11-29 3 views
3

클라이언트 - 서버 프로그램을 만들고 있습니다. 서버는 클라이언트에 숫자 범위를 보내고 클라이언트는 범위에서 작업을 수행하고 (완벽한 숫자를 찾습니다) 결과를 보냅니다. 서버는 Python으로 작성하고 C에서 클라이언트는 여기에 내 코드입니다 :C 및 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() 

클라이언트 (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); 
} 

이 프로그램은 잘에 작동 첫 번째 실행은 두 번 또는 여러 번 실행 한 후 서버에 숫자 범위를 클라이언트에 보내려고하면 socket.error: [Errno 111] Connection refused이라는 예외가 발생합니다. 나는 적절하게 연결을 닫지 않을 것이라고 생각하지만 내가 뭘 잘못하고 있는지 알 수 없다. 어떤 도움을 주시면 감사하겠습니다.

답변

4

두 프로그램 사이에 여러 개의 TCP 연결이 필요하지 않습니다. 하나는 전이중이므로 충분합니다.

난 당신이 여러분의 인생을 더 쉽게 만드는 것을 제안하고 서버 알려진 포트에의 서버 소켓을 결합 가능 클라이언트/서버 디자인을 따를 것입니다, 클라이언트 동안, 및 서비스를 받아, 클라이언트 연결 수신을 알려진 주소와 포트에 연결 한 다음 단일 TCP 연결을 통해 메시지를 보내고받습니다 (정의한 일부 응용 프로그램 프로토콜에 따라).