我程序中的一个线程需要发送好几个大的double数组给另外一个程序。线程本身是通过指针得到数组的地址的。现在我不知道怎么方便的发送数组给零位一个程序,并且能把字符类型和double类型互相转换。现在我是每次发送一个数组,并且复制每一个元素的。感觉这是一个超级笨的办法,而且实际用起来速度很慢。
请问我应该怎么做?请大家帮忙。
//发送端
n=0;
for(j=0;j<Ny;j++)
for(i=0;i<Nx;i++)
n += sprintf(sendBuf+n,"%16.10f",u[j][i]);
send(sockConn,sendBuf,n,0);//接收端
n=Nx*Ny*16;
recv(sockClient,recvBuf,n,0);
for(j=0;j<Ny;j++)
for(i=0;i<Nx;i++)
u[j][i]= atof(recvBuf+(j*Nx+i)*16);
请问我应该怎么做?请大家帮忙。
//发送端
n=0;
for(j=0;j<Ny;j++)
for(i=0;i<Nx;i++)
n += sprintf(sendBuf+n,"%16.10f",u[j][i]);
send(sockConn,sendBuf,n,0);//接收端
n=Nx*Ny*16;
recv(sockClient,recvBuf,n,0);
for(j=0;j<Ny;j++)
for(i=0;i<Nx;i++)
u[j][i]= atof(recvBuf+(j*Nx+i)*16);
1.把 浮点数当作 字符串来传送
2.直接发送内存缓冲区
但是直接发送缓冲区会引起一个问题,如果客户端和服务端在不同的cpu体系架构下,发送16位数和32位数和浮点数的时候会引起 数据解释出错。因为 intel cpu,sun sparc cpu,ibm powerpc cpu,dec alpha cpu采用的表示整数和浮点数的方式不一样。有的是高8(16)位在前,有的是低8(16)为在前。所以你在intel cpu windows下发送一个整数“16”或者浮点数到一个采用sparc cpu的solaris系统下,它按照它的内存结构解释出来,就肯定不是16了!这就是所谓的big-endian和little-endian。 如果要直接发送内存缓冲区,则需要将缓冲区打包一下,目前有两种方式。
1.采用sun rpc里边的数据打包格式 External Data Representation(Sun's XDR Package)
2.采用corbo标准的Common Data Representation (CDR)
前一个被firebird开源数据库采用,后一个是ACE使用的跨平台数据打包格式.
都可以找到示例代码。
可以直接发送缓冲区,不过这样的话,你的服务器就不是“跨平台”的了。直接发送缓冲区代码如下
int dim1 = 5;
SOCKET s;double (*pia)[512] = new double[dim1][512];
send(s,reinterpret_cast<const char *>( pia),dim1*512*sizeof(double),0);服务器端接受到后再进行指针转换
//发送端
n=Nx*Ny*sizeof(double);
memcpy(recvBuf,(char*)(u[0]),n);
if(n != send(sockClient,recvBuf,n,0))
break;//接收端
n=Nx*Ny*sizeof(double);
recv(sockConn,sendBuf,n,0);
memcpy((char*)(u[0]), sendBuf, n);我用这种方法发送成功了,在单机上模拟可以。但是好像在两台机器上(同一结构)有问题。
int dim1 = 5;
SOCKET s;double (*pia)[512] = new double[dim1][512];
send(s,reinterpret_cast<const char *>( pia),dim1*512*sizeof(double),0);服务器端接受到后再进行指针转换
代码如下size_t readn(SOCKET fd, char *vptr, size_t n)
{
size_t nleft;
size_t nread;
char *ptr; ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nread = recv(fd, ptr, nleft,0)) == SOCKET_ERROR) {
return(-1); //error
} else if (nread == 0)
break; nleft -= nread;
ptr += nread;
}
return(n - nleft); //succ recv n
}char sz_recv_buf[5*512*sizeof(double)]={0};
int nRet;
double **myp;nRet = readn(sockConn,sz_recv_buf,5*512*sizeof(double));
if (nRet == -1)
{
//错误处理
}
else
{
myp = reinterpret_cast<double **>(sz_recv_buf);
int i,j;
for (i=0;i<5;i++)
{
for (j=0;j<512;j++)
printf("value is %d \t\n",myp[i][j]);
}
}
1.采用sun rpc里边的数据打包格式 External Data Representation(Sun's XDR Package)
2.采用corbo标准的Common Data Representation (CDR)这两种办法我怎么都没有找到相应的资料。我对这挺有兴趣。