我正在开发一个应用程序,其中许多客户端应连接到服务器应用程序并每分钟传输一个大约300字节的字符串。客户端只是RS232和套接字服务器之间的网关。客户端和服务器之间的连接使用openssl进行SSL加密。两者都是用C ++开发的。
传输正在全天候运行,但如果某些数据丢失则并不重要。
首先我尝试使用TCP连接,但是我遇到了麻烦,因为连接断了一些。因此,当我发送信息时,我决定连接并断开每一分钟(也许稍后我将缓存一些数据并且不是每分钟发送一次)。因此我认为与DTLS使用UDP连接会更好。
但我有两个UDP连接问题。
ca每10个字符串都有一个缺少的字符。这不是很关键,但是我的代码可能不是错误吗?
如果我使用“SSL_CTX_load_verify_locations”验证我的客户端,我有时会收到错误:“SSL connect:message too long”。 我认为通常应该是超过64K的消息?但在连接时我不发送任何数据?如何在连接时发生这种情况?
你认为UDP对我来说是正确的协议吗?或者我应该使用TCP?
以下是我的代码中的一些细节:
服务器:
server_addr.s4.sin_family = AF_INET;
server_addr.s4.sin_addr.s_addr = INADDR_ANY;
server_addr.s4.sin_port = htons(port);
THREAD_setup();
OpenSSL_add_ssl_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(DTLSv1_server_method());
SSL_CTX_set_cipher_list(ctx, "ALL:NULL:eNULL:aNULL");
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
if (!SSL_CTX_use_certificate_file(ctx, SERVERCERT, SSL_FILETYPE_PEM))
printf("\nERROR: no certificate found!");
if (!SSL_CTX_use_PrivateKey_file(ctx, SERVERKEY, SSL_FILETYPE_PEM))
printf("\nERROR: no private key found!");
if (!SSL_CTX_check_private_key (ctx))
printf("\nERROR: invalid private key!");
if(!SSL_CTX_load_verify_locations(ctx, CACERT, NULL))
cout << "\nERROR: no ca-cert found!\n";
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, dtls_verify_callback);
SSL_CTX_set_read_ahead(ctx, 1);
SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie);
SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie);
fd = socket(server_addr.ss.ss_family, SOCK_DGRAM, 0);
if (fd < 0) {
perror("socket");
exit(-1);
}
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on));
bind(fd, (const struct sockaddr *) &server_addr, sizeof(struct sockaddr_in));
while (1)
{
memset(&client_addr, 0, sizeof(struct sockaddr_storage));
bio = BIO_new_dgram(fd, BIO_NOCLOSE);
timeout.tv_sec = 5;
timeout.tv_usec = 0;
BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
ssl = SSL_new(ctx);
SSL_set_bio(ssl, bio, bio);
SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
while (DTLSv1_listen(ssl, &client_addr) <= 0);
info = (struct pass_info*) malloc (sizeof(struct pass_info));
memcpy(&info->server_addr, &server_addr, sizeof(struct sockaddr_storage));
memcpy(&info->client_addr, &client_addr, sizeof(struct sockaddr_storage));
info->ssl = ssl;
if (pthread_create( &tid, NULL, connection_handle, info) != 0) {
perror("pthread_create");
exit(-1);
}
}
THREAD_cleanup();
}
客户端:
OpenSSL_add_ssl_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(DTLSv1_client_method());
SSL_CTX_set_cipher_list(ctx, "eNULL:!MD5");
if (!SSL_CTX_use_certificate_file(ctx, CLIENTCERT, SSL_FILETYPE_PEM))
printf("\nERROR: no certificate found!");
if (!SSL_CTX_use_PrivateKey_file(ctx, CLIENTKEY, SSL_FILETYPE_PEM))
printf("\nERROR: no private key found!");
if (!SSL_CTX_check_private_key (ctx))
printf("\nERROR: invalid private key!");
if(!SSL_CTX_load_verify_locations(ctx,CACERT,NULL))
cout << "\nERROR: cannot load CA Cert file for verification!\n";
SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
SSL_CTX_set_read_ahead(ctx, 1);
ssl = SSL_new(ctx);
bio = BIO_new_dgram(fd, BIO_CLOSE);
connect(fd, (struct sockaddr *) &remote_addr, sizeof(struct sockaddr_in));
BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &remote_addr.ss);
SSL_set_bio(ssl, bio, bio);
if (SSL_connect(ssl) < 0) {
perror("SSL_connect");
printf("%s\n", ERR_error_string(ERR_get_error(), buf));
exit(-1);
}
timeout.tv_sec = 3;
timeout.tv_usec = 0;
BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);