[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