[MPICH] Sockets code inside MPI

Andrew Hakman andrew.hakman at gmail.com
Tue May 22 11:38:09 CDT 2007


Hi

Is there something special I have to do to write sockets code in my
MPI program? The master process needs to be a network server and
receive requests from a client process. The code works when I don't
include any MPI calls, but as soon as I introduce MPI calls, the
socket receive always returns -1. Here is the code

const short MYPORT = 6000;

int main(int argc, char **argv)
{
    //MPI variables
    int my_rank;
    int com_size;

    //start MPI
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &com_size);

    //start "evaluate server" and wait for requests
    struct sockaddr_in my_addr, from;
    socklen_t from_len;
    int sd, client_sd, sendlen, recvlen;
    double result;
    socklen_t len;
    int i;
    bzero((char *)&my_addr, sizeof(my_addr));
    if ((sd=socket(AF_INET,SOCK_STREAM,0)) < 0)
    {
        printf("Problem creating socket\n");
        exit(1);
    }
    my_addr.sin_family = AF_INET;
    my_addr.sin_addr.s_addr=INADDR_ANY; //fill with local IP
    my_addr.sin_port = htons(MYPORT);
    if (bind(sd, (struct sockaddr *)&my_addr, sizeof(my_addr))<0)
    {
        printf("Error binding to socket\n");
        exit(1);
    }
    if (listen(sd,5)<0)
    {
        printf("Error listening\n");
        exit(1);
    }
    printf("Evaluate Server Ready and listening...\n");
    for (;;)
    {
        client_sd=accept(sd,(struct sockaddr *)&from,&from_len);
        printf("got request, solving profile\n");
        double var[nParams];
        double result;
        double f=0.0;
        recvlen=-1;
        while(recvlen<0)
        {
            recvlen=recv(client_sd,&var,sizeof(double)*nParams,0);
        }
        printf("master, ");
        for (int j=0; j<nParams; j++)
        {
            printf("%f, ",var[j]);
        }
        printf("\n");
/*        MPI_Bcast(&var, nParams, MPI_DOUBLE, 0, MPI_COMM_WORLD);

        //collect up fitness values
        MPI_Reduce(&f, &result, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
 */
        //send total fitness value back to the client
        sendlen=send(client_sd,(void *)&result,sizeof(result),0);
        close(client_sd);
    }
    MPI_Finalize();
    return 0;
}

To summarize, a fixed length double array is sent from the client to
the server, and a single double is to be sent back to the client as a
result.

If I comment out MPI_Init and MPI_Finalize, the receive (just after
the accept) works perfectly. If I have MPI_Init and MPI_Finalize in,
the program spins forever in the while(recvlen<0) loop.

I can't see it being an issue with something else using port 6000 as I
would expect (and do see when I kill the process and restart it too
quickly) error when calling bind.

A self contained example client code would be the following (the real
client code is somewhat convoluted as it's tied into Matlab):

int main()
{
    int i;
    double returnval;
    double var[] = {3.455, 0.38, 20.21, 3.39959, 0.156085, -4.10835,
0.700964, 0.123453, -17.3804, 2.77002, 4.0, 0.6, 1.40733, 9.0, 0.6,
-5.61955, 0.031321};
//    for (i=0; i<nParams; i++)
//    {
//       printf("element %d = %f\n",i,var[i]);
//    }
    returnval = evaluate(var);
    printf("returnval=%f\n",returnval);
}

/*****************************************************************************\
|  This evaluate function is an interface to talk to MPI from MATLAB          |
\*****************************************************************************/
double evaluate(const double * var)
{
    //open socket to "evaluate server" on the master node
    struct sockaddr_in my_addr;
    struct hostent *hp;
    int sd, sendlen, recvlen;
    double result;
    socklen_t len;

    bzero((char *)&my_addr, sizeof(my_addr));
    if ((sd=socket(AF_INET,SOCK_STREAM,0)) < 0)
    {
        printf("Problem creating socket\n");
        exit(1);
    }
    my_addr.sin_family = AF_INET;
    if ((hp = gethostbyname(MYHOST))==0)
    {
        printf("Invalid or unknown host\n");
        exit(1);
    }
    memcpy(&my_addr.sin_addr.s_addr, hp->h_addr, hp->h_length);
    my_addr.sin_port = htons(MYPORT);
    if (connect(sd,(sockaddr*)&my_addr,sizeof(my_addr))<0)
    {
        printf("Error connecting to evaluate server\n");
        exit(1);
    }
    for (int k=0; k<nParams; k++)
    {
        mexPrintf("var[k]=%f\n",var[k]);
    }
    sendlen=send(sd,(void*)var,sizeof(double)*nParams,0);
    mexPrintf("sendlen=%d\n",sendlen);
    recvlen=recv(sd,&result,sizeof(result),0);
    close(sd);
    return result;
}

Thanks,
Andrew




More information about the mpich-discuss mailing list