Can SEALContext object transmit by socket?
Can SEALContext object transmit by socket?
I want to use socket to imitate the comminucations between server and clients. Then I write code to acchieve the fundation. But some errors occured.
If I write parameters for SEALContext object in Client, it can print corectly. However, I can not suitable for the parameters from Server.
I will show you the code.
server:
`#include <server.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
using namespace seal;
const int PORT = 8000;
#define MaxClient 10
#define MaxBufSize 4096
#define _CRT_SECURE_NO_WARINGS
//服务线程
DWORD WINAPI ServerThread(LPVOID lpParameter) {
SOCKET* ClientSocket = (SOCKET*)lpParameter;
int receByt = 0;
//* char RecvBuf[MaxBufSize];
char RecvBuf[1];
char SendBuf[MaxBufSize];
while (1) {
//数据接收
receByt = recv(*ClientSocket, RecvBuf, sizeof(RecvBuf), 0);
cout << "receByt = " << receByt << endl;
string str_buff = RecvBuf;
cout << "str_buff = " << str_buff << endl;
if (receByt > 0) {
cout << "接收到的消息是:" << RecvBuf << " 来自客户端:" << *ClientSocket << endl;
if (str_buff == "1") {
cout << "If you are ready for FHE servive,please write 1" << endl;
}
else
cout << "Service wronged!" << endl;
}
else
{
cout << "接收消息结束!" << endl;
break;
}
memset(RecvBuf, 0, sizeof(RecvBuf));
//数据处理
//数据发送
fgets(SendBuf, MaxBufSize, stdin);
EncryptionParameters parms(scheme_type::bfv);
size_t poly_modulus_degree = 8192;
parms.set_poly_modulus_degree(poly_modulus_degree);
parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree));
parms.set_plain_modulus(PlainModulus::Batching(poly_modulus_degree, 20));
SEALContext context(parms);
print_parameters(context);
int k = 0;
//k = send(*ClientSocket, (char*)&parms, sizeof(EncryptionParameters), 0);
k = send(*ClientSocket, (char*)&context, sizeof(SEALContext), 0);
if (k < 0) {
cout << "发送失败" << endl;
}
/* //source
cout << "请输入要发送到客户端的信息:" << endl;
fgets(SendBuf, MaxBufSize, stdin);
int k = 0;
k = send(*ClientSocket, SendBuf, sizeof(SendBuf), 0);
if (k < 0) {
cout << "发送失败" << endl;
}
memset(SendBuf, 0, sizeof(SendBuf));
*/ } closesocket(*ClientSocket); free(ClientSocket); return 0; }
int main() { WSAData wsd; WSAStartup(MAKEWORD(2, 2), &wsd); SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN ListenAddr; ListenAddr.sin_family = AF_INET; ListenAddr.sin_addr.S_un.S_addr = INADDR_ANY;//表示填入本机ip ListenAddr.sin_port = htons(PORT); int n; //n = bind(ListenSocket, (LPSOCKADDR)&ListenAddr, sizeof(ListenAddr)); n = ::bind(ListenSocket, (LPSOCKADDR)&ListenAddr, sizeof(ListenAddr));
if (n == SOCKET_ERROR) {
cout << "端口绑定失败!" << endl;
return -1;
}
else {
cout << "端口绑定成功:" << PORT << endl;
}
int l = listen(ListenSocket, 20);
cout << "服务端准备就绪,等待连接请求" << endl;
while (1) {
//循环接收客户端连接请求并创建服务线程
SOCKET* ClientSocket = new SOCKET;
ClientSocket = (SOCKET*)malloc(sizeof(SOCKET));
//接收客户端连接请求
int SockAddrlen = sizeof(sockaddr);
*ClientSocket = accept(ListenSocket, 0, 0);
cout << "一个客户端已连接到服务器,socket是:" << *ClientSocket << endl;
CreateThread(NULL, 0, &ServerThread, ClientSocket, 0, NULL);
}//while
closesocket(ListenSocket);
WSACleanup();
return(0);
}//main`
client: `//#include "Client.h" #include "client.h" #pragma comment(lib,"ws2_32.lib") #pragma warning(disable:4996) using namespace std; using namespace seal; const int PORT = 8000; #define MaxBufSize 4096 #define _CRT_SECURE_NO_WARINGS int main() { WSADATA wsd; WSAStartup(MAKEWORD(2, 2), &wsd); //* SOCKET SocketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKET SocketClient = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN ClientAddr;
ClientAddr.sin_family = AF_INET;
ClientAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
ClientAddr.sin_port = htons(PORT);
int n = 0;
n = connect(SocketClient, (struct sockaddr*)&ClientAddr, sizeof(ClientAddr));
if (n == SOCKET_ERROR) {
cout << "连接失败" << endl;
return -1;
}
cout << "已经连接到服务器,可以向服务器发送消息了!" << endl;
char info[1024], SendBuff[MaxBufSize], RecvBuff[MaxBufSize];
while (1) {
//* cout << "请输入要发送的信息,按回车结束发送:" << endl; //数据处理
cout << "If you are ready for FHE ,please write 1" << endl;
//数据处理结束,准备发送数据
fgets(info, 1024, stdin);
//* gets(info); //error,change to the former
if (info[0] == '\0')
break;
strcpy(SendBuff, info);
memset(info, 0, sizeof(info));
int k = 0;
k = send(SocketClient, SendBuff, sizeof(SendBuff), 0);
memset(SendBuff, 0, sizeof(SendBuff));
if (k < 0) {
cout << "发送失败" << endl;
}
Sleep(500);
//数据接收
EncryptionParameters parms(scheme_type::bfv);
int m = 0;
//n = recv(SocketClient, (char*)&parms, sizeof(EncryptionParameters), 0);
/*
size_t poly_modulus_degree = 8192;
parms.set_poly_modulus_degree(poly_modulus_degree);
parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree));
parms.set_plain_modulus(PlainModulus::Batching(poly_modulus_degree, 20));
m = 1;
*/
SEALContext context(parms);
m = recv(SocketClient, (char*)&context, sizeof(SEALContext), 0);
cout << "m = " << m << endl;
if (m > 0) {
cout << "Having got the paramerters" << endl;
//SEALContext context(parms);
print_parameters(context); //error,异常,读取访问权限冲突
cout << endl;
}
memset(RecvBuff, 0, sizeof(RecvBuff));
/*//*
int n = 0;
n = recv(SocketClient, RecvBuff, sizeof(RecvBuff), 0);
if (n > 0) {
cout << "接收到来自服务器的消息为:" << RecvBuff << endl;
}
memset(RecvBuff, 0, sizeof(RecvBuff));
*/
}
closesocket(SocketClient);
WSACleanup();
return 0;
} `
- It seems you have misunderstood what
sizeof(EncryptionParameters)means. - Instead using
std::stringstreamto de/serializestd::stringstream ss; parms.save(ss); std::string parms_to_send = ss.str();
Then on the other side, first recv a string and use std::stringstream to de-serialize
EncryptionParmeters parms;
parms.load(a_string);
SEALContext is not serializable. Just exchange EncryptionParmeters and then construct the context.
- It seems you have misunderstood what
sizeof(EncryptionParameters)means.- Instead using
std::stringstreamto de/serializestd::stringstream ss; parms.save(ss); std::string parms_to_send = ss.str();Then on the other side, first recv a string and use
std::stringstreamto de-serializeEncryptionParmeters parms; parms.load(a_string);
SEALContextis not serializable. Just exchangeEncryptionParmetersand then construct the context.
Well, I tried this method, I can get string data, however, parms.load can't load it and throw exception. For function load() just can support stream datatype, I convert string to stringstream.
For thinking about it, for get the parms, may use parms.save() and parms.load() to do this?
When I use simply parms.save(ss) and parms.load(ss), it not work and throw logic_error. So I use "parms.save(reinterpret_cast<seal_byte*>(byte_buffer.data()), byte_buffer.size()); ", it works. However, when constract SEALContext, it throw std::invalid_argument error. I have no idea about it. Can you give me some advice?

The following code work fine for me
void test() {
seal::EncryptionParameters parms(seal::scheme_type::ckks);
size_t N = 8192;
std::vector<int> modulus_bits = {51, 55, 55};
auto modulus = seal::CoeffModulus::Create(N, modulus_bits);
parms.set_poly_modulus_degree(N);
parms.set_coeff_modulus(modulus);
parms.set_random_generator(
seal::UniformRandomGeneratorFactory::DefaultFactory());
seal::SEALContext conetxt(parms);
std::ostringstream outs;
parms.save(outs);
std::string parms_str = outs.str();
printf("parms bytes %zd\n", parms_str.length());
// Simulate: send string through socket
std::vector<unsigned char> recv_bytes(parms_str.length());
std::copy_n(parms_str.c_str(), recv_bytes.size(), recv_bytes.data());
// wrap the bits as string
std::string recv_string(recv_bytes.data(), recv_bytes.data() + recv_bytes.size());
std::istringstream ins(recv_string);
seal::EncryptionParameters other_parms;
other_parms.load(ins);
seal::SEALContext other_context(other_parms);
printf("Is SEAL ok = %d\n", other_context.parameters_set());
}
The following code work fine for me
void test() { seal::EncryptionParameters parms(seal::scheme_type::ckks); size_t N = 8192; std::vector<int> modulus_bits = {51, 55, 55}; auto modulus = seal::CoeffModulus::Create(N, modulus_bits); parms.set_poly_modulus_degree(N); parms.set_coeff_modulus(modulus); parms.set_random_generator( seal::UniformRandomGeneratorFactory::DefaultFactory()); seal::SEALContext conetxt(parms); std::ostringstream outs; parms.save(outs); std::string parms_str = outs.str(); printf("parms bytes %zd\n", parms_str.length()); // Simulate: send string through socket std::vector<unsigned char> recv_bytes(parms_str.length()); std::copy_n(parms_str.c_str(), recv_bytes.size(), recv_bytes.data()); // wrap the bits as string std::string recv_string(recv_bytes.data(), recv_bytes.data() + recv_bytes.size()); std::istringstream ins(recv_string); seal::EncryptionParameters other_parms; other_parms.load(ins); seal::SEALContext other_context(other_parms); printf("Is SEAL ok = %d\n", other_context.parameters_set()); }
It seems you don't use socket to transmit data, you just use stringstream to do. Socket use send() and recv() to communicate. The fomat like: send( In SOCKET s, In_reads_bytes(len) const char FAR * buf, In int len, In int flags ); recv( In SOCKET s, Out_writes_bytes_to(len, return) __out_data_source(NETWORK) char FAR * buf, In int len, In int flags ); Always it make client and server be two projects like following picture (project Clients and Server_for_multi_clients), you should define apart.
There is no difference between copy_n and send/recv pair.
To make sure you are using the right length (but not just a MaxBufSize) and make sure your have initialized your byte vector properly.
There is no difference between
copy_nandsend/recvpair. To make sure you are using the right length (but not just aMaxBufSize) and make sure your have initialized your byte vector properly.
I have try what you said. For me, I set client project and service project apart, when client.cpp use the following data to recv parms that works.
std::vector