Надо организовать клиент сервер с шифрованием средством openssl.
server.c
//----------------------------------------------------
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>#include <stdio.h>
#include <string.h>main()
{
BIO *sbio, *bbio, *acpt, *out;
int len;
char tmpbuf[1024];
SSL_CTX *ctx;
SSL *ssl;
ERR_load_crypto_strings();
ERR_load_SSL_strings();
OpenSSL_add_all_algorithms();
SSL_library_init();
/* Might seed PRNG here */
ctx=SSL_CTX_new(SSLv23_server_method());
if(ctx == NULL)
{
printf("CTX is null\n");
return;
}
printf("After Cert Load\n");
if (!SSL_CTX_use_certificate_file(ctx,"certfiles/cacert.pem", SSL_FILETYPE_PEM)
|| SSL_CTX_use_PrivateKey_file(ctx,"certfiles/rsa_private_key.pem", SSL_FILETYPE_PEM)
|| SSL_CTX_check_private_key(ctx))
{
fprintf(stderr, "Error setting up SSL_CTX\n");
ERR_print_errors_fp(stderr);
return 0;
}
printf("After Cert Load\n ");
/* Might do other things here like setting verify locations and
* DH and/or RSA temporary key callbacks
*/
/* New SSL BIO setup as server */
sbio=BIO_new_ssl(ctx,0);
BIO_get_ssl(sbio, &ssl);
if(!ssl) {
fprintf(stderr, "Can't locate SSL pointer\n");
/* whatever ... */
}
/* Don't want any retries */
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
/* Create the buffering BIO */
bbio = BIO_new(BIO_f_buffer());
/* Add to chain */
sbio = BIO_push(bbio, sbio);
acpt=BIO_new_accept("1332");
/* By doing this when a new connection is established
* we automatically have sbio inserted into it. The
* BIO chain is now 'swallowed' by the accept BIO and
* will be freed when the accept BIO is freed.
*/
BIO_set_accept_bios(acpt,sbio);
out = BIO_new_fp(stdout, BIO_NOCLOSE);
/* Setup accept BIO */
if(BIO_do_accept(acpt) <= 0) {
fprintf(stderr, "Error setting up accept BIO\n");
ERR_print_errors_fp(stderr);
return 0;
}
/* Now wait for incoming connection */
if(BIO_do_accept(acpt) <= 0) {
fprintf(stderr, "Error in connection\n");
ERR_print_errors_fp(stderr);
return 0;
}
/* We only want one connection so remove and free
* accept BIO
*/
sbio = BIO_pop(acpt);
BIO_free_all(acpt);
if(BIO_do_handshake(sbio) <= 0)
{
fprintf(stderr, "Error in SSL handshake\n");
ERR_print_errors_fp(stderr);
return 0;
}
BIO_puts(sbio, "HTTP/1.0 200 OK\r\nContent-type: text/plain\r\n\r\n");
BIO_puts(sbio, "\r\nConnection Established\r\nRequest headers:\r\n");
BIO_puts(sbio, "--------------------------------------------------\r\n");
for(;;) {
len = BIO_gets(sbio, tmpbuf, 1024);
if(len <= 0) break;
BIO_write(sbio, tmpbuf, len);
BIO_write(out, tmpbuf, len);
/* Look for blank line signifying end of headers*/
if((tmpbuf[0] == '\r') || (tmpbuf[0] == '\n')) break;
}
BIO_puts(sbio, "--------------------------------------------------\r\n");
BIO_puts(sbio, "\r\n");
/* Since there is a buffering BIO present we had better flush it */
BIO_flush(sbio);
BIO_free_all(sbio);
}
//----------------------------------------------------
client.c
//----------------------------------------------------
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>#include <stdio.h>
#include <string.h>main()
{
BIO *sbio, *out;
int len;
char tmpbuf[1024];
SSL_CTX *ctx;
SSL *ssl;
ERR_load_crypto_strings();
ERR_load_SSL_strings();
OpenSSL_add_all_algorithms();
SSL_library_init();
/* We would seed the PRNG here if the platform didn't
* do it automatically
*/
ctx = SSL_CTX_new(SSLv23_client_method());
/* We'd normally set some stuff like the verify paths and
* mode here because as things stand this will connect to
* any server whose certificate is signed by any CA.
*/
sbio = BIO_new_ssl_connect(ctx);
BIO_get_ssl(sbio, &ssl);
if(!ssl) {
fprintf(stderr, "Can't locate SSL pointer\n");
/* whatever ... */
}
/* Don't want any retries */
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
/* We might want to do other things with ssl here */
BIO_set_conn_hostname(sbio, "localhost:1332");
out = BIO_new_fp(stdout, BIO_NOCLOSE);
if(BIO_do_connect(sbio) <= 0) {
fprintf(stderr, "Error connecting to server\n");
ERR_print_errors_fp(stderr);
/* whatever ... */
}
if(BIO_do_handshake(sbio) <= 0) {
fprintf(stderr, "Error establishing SSL connection\n");
ERR_print_errors_fp(stderr);
/* whatever ... */
}
/* Could examine ssl here to get info */
BIO_puts(sbio, "GET / HTTP/1.0\n\n");
for(;;) {
len = BIO_read(sbio, tmpbuf, 1024);
if(len <= 0) break;
BIO_write(out, tmpbuf, len);
}
BIO_free_all(sbio);
BIO_free(out);
}//----------------------------------------------------
Когда клиент коннектится сервер вылетает со следующим текстом:
$ ./recv
After Cert Load
Enter PEM pass phrase:
After Cert Load
Error in SSL handshake
23749:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:/usr/src/secure/lib/libssl/../../../crypto/openssl/ssl/s3_srvr.c:974:
А клиент с таким:
$ ./send
Error connecting to server
24080:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:/usr/src/secure/lib/libssl/../../../crypto/openssl/ssl/s23_clnt.c:562:
Error establishing SSL connection
24080:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:/usr/src/secure/lib/libssl/../../../crypto/openssl/ssl/s23_clnt.c:562:
Вот собственно и проблема.
Заранее спасибо
Студентам здесь не подают. Если уж стырил код, то напряги то, что замещает у тебя мозг, и почитай хотя бы лекции.
>то напряги то, что замещает у тебя мозгОн и напрягает -- форум. %)
>, и почитай хотя бы лекции.
Осторожно, а то вдруг и это оно только ч/з форум умеет??! |))
вот здесь ошибка:main()
{
BIO *sbio, *bbio, *acpt, *out;
int len;
char tmpbuf[1024];
SSL_CTX *ctx;
SSL *ssl;
ERR_load_crypto_strings();
ERR_load_SSL_strings();
OpenSSL_add_all_algorithms();
SSL_library_init();
/* Might seed PRNG here */
ctx=SSL_CTX_new(SSLv23_server_method());
if(ctx == NULL)
{
printf("CTX is null\n");
return;
}
printf("After Cert Load\n");
if (!SSL_CTX_use_certificate_file(ctx,"certfiles/cacert.pem", SSL_FILETYPE_PEM)
|| SSL_CTX_use_PrivateKey_file(ctx,"certfiles/rsa_private_key.pem", SSL_FILETYPE_PEM)
|| SSL_CTX_check_private_key(ctx))
{
fprintf(stderr, "Error setting up SSL_CTX\n");
ERR_print_errors_fp(stderr);
return 0;
}
printf("After Cert Load\n ");
/* Might do other things here like setting verify locations and
* DH and/or RSA temporary key callbacks
*/
/* New SSL BIO setup as server */
sbio=BIO_new_ssl(ctx,0);
BIO_get_ssl(sbio, &ssl);
if(!ssl) {
fprintf(stderr, "Can't locate SSL pointer\n");
/* whatever ... */
}
/* Don't want any retries */
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
/* Create the buffering BIO */
bbio = BIO_new(BIO_f_buffer());
/* Add to chain */
sbio = BIO_push(bbio, sbio);
acpt=BIO_new_accept("1332");
/* By doing this when a new connection is established
* we automatically have sbio inserted into it. The
* BIO chain is now 'swallowed' by the accept BIO and
* will be freed when the accept BIO is freed.
*/
BIO_set_accept_bios(acpt,sbio);
out = BIO_new_fp(stdout, BIO_NOCLOSE);
/* Setup accept BIO */
if(BIO_do_accept(acpt) <= 0) {
fprintf(stderr, "Error setting up accept BIO\n");
ERR_print_errors_fp(stderr);
return 0;
}
/* Now wait for incoming connection */
if(BIO_do_accept(acpt) <= 0) {
fprintf(stderr, "Error in connection\n");
ERR_print_errors_fp(stderr);
return 0;
}
/* We only want one connection so remove and free
* accept BIO
*/
sbio = BIO_pop(acpt);
BIO_free_all(acpt);
if(BIO_do_handshake(sbio) <= 0)
{
fprintf(stderr, "Error in SSL handshake\n");
ERR_print_errors_fp(stderr);
return 0;
}
BIO_puts(sbio, "HTTP/1.0 200 OK\r\nContent-type: text/plain\r\n\r\n");
BIO_puts(sbio, "\r\nConnection Established\r\nRequest headers:\r\n");
BIO_puts(sbio, "--------------------------------------------------\r\n");
for(;;) {
len = BIO_gets(sbio, tmpbuf, 1024);
if(len <= 0) break;
BIO_write(sbio, tmpbuf, len);
BIO_write(out, tmpbuf, len);
/* Look for blank line signifying end of headers*/
if((tmpbuf[0] == '\r') || (tmpbuf[0] == '\n')) break;
}
BIO_puts(sbio, "--------------------------------------------------\r\n");
BIO_puts(sbio, "\r\n");
/* Since there is a buffering BIO present we had better flush it */
BIO_flush(sbio);
BIO_free_all(sbio);
}
//----------------------------------------------------
client.c
//----------------------------------------------------
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>#include <stdio.h>
#include <string.h>main()
{
BIO *sbio, *out;
int len;
char tmpbuf[1024];
SSL_CTX *ctx;
SSL *ssl;
ERR_load_crypto_strings();
ERR_load_SSL_strings();
OpenSSL_add_all_algorithms();
SSL_library_init();
/* We would seed the PRNG here if the platform didn't
* do it automatically
*/
ctx = SSL_CTX_new(SSLv23_client_method());
/* We'd normally set some stuff like the verify paths and
* mode here because as things stand this will connect to
* any server whose certificate is signed by any CA.
*/
sbio = BIO_new_ssl_connect(ctx);
BIO_get_ssl(sbio, &ssl);
if(!ssl) {
fprintf(stderr, "Can't locate SSL pointer\n");
/* whatever ... */
}
/* Don't want any retries */
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
/* We might want to do other things with ssl here */
BIO_set_conn_hostname(sbio, "localhost:1332");
out = BIO_new_fp(stdout, BIO_NOCLOSE);
if(BIO_do_connect(sbio) <= 0) {
fprintf(stderr, "Error connecting to server\n");
ERR_print_errors_fp(stderr);
/* whatever ... */
}
if(BIO_do_handshake(sbio) <= 0) {
fprintf(stderr, "Error establishing SSL connection\n");
ERR_print_errors_fp(stderr);
/* whatever ... */
}
/* Could examine ssl here to get info */
BIO_puts(sbio, "GET / HTTP/1.0\n\n");
for(;;) {
len = BIO_read(sbio, tmpbuf, 1024);
if(len <= 0) break;
BIO_write(out, tmpbuf, len);
}
BIO_free_all(sbio);
BIO_free(out);
}
Проблема преобразилась в другую
server.c
//-------------
#include "stdio.h"
#include "string.h"#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"int password_callback(char *buf, int size, int rwflag, void *userdata)
{
/* For the purposes of this demonstration, the password is "ibmdw" */printf("*** Callback function called\n");
strcpy(buf, "ibmdw");
return 1;
}int main()
{
SSL_CTX *ctx;
SSL *ssl;
BIO *bio, *abio, *out, *sbio;
char tmpbuf[1024];
int len;int (*callback)(char *, int, int, void *) = &password_callback;
printf("Secure Programming with the OpenSSL API, Part 4:\n");
printf("Serving it up in a secure manner\n\n");SSL_load_error_strings();
ERR_load_BIO_strings();
ERR_load_SSL_strings();
OpenSSL_add_all_algorithms();
SSL_library_init();printf("Attempting to create SSL context... ");
ctx = SSL_CTX_new(SSLv23_server_method());
if(ctx == NULL)
{
printf("Failed. Aborting.\n");
return 0;
}printf("\nLoading certificates...\n");
SSL_CTX_set_default_passwd_cb(ctx, callback);
if(!SSL_CTX_use_certificate_file(ctx, "certificate.pem", SSL_FILETYPE_PEM))
{
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
return 0;
}
if(!SSL_CTX_use_PrivateKey_file(ctx, "private.key", SSL_FILETYPE_PEM))
{
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
return 0;
}printf("Attempting to create BIO object... ");
bio = BIO_new_ssl(ctx, 0);
if(bio == NULL)
{
printf("Failed. Aborting.\n");
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
return 0;
}printf("\nAttempting to set up BIO for SSL...\n");
BIO_get_ssl(bio, &ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
abio = BIO_new_accept("4422");
BIO_set_accept_bios(abio, bio);printf("Waiting for incoming connection...\n");
if(BIO_do_accept(abio) <= 0)
{
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
BIO_free_all(bio);
BIO_free_all(abio);
return;
}if(BIO_do_accept(abio) <= 0)
{
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
BIO_free_all(bio);
BIO_free_all(abio);
return;
}out = BIO_pop(abio);
if(BIO_do_handshake(out) <= 0)
{
printf("Handshake failed.\n");
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
BIO_free_all(bio);
BIO_free_all(abio);
return;
}BIO_puts(out, "Hello\n");
//Read end
for(;;) {
len = BIO_read(sbio, tmpbuf, 1024);
if(len <= 0) break;
tmpbuf[len]='\0';
}
printf("%s", tmpbuf);
//Read end
if(strcmp(tmpbuf,"Hello\n")==0)
{
printf("Hello received sending user request\n");
BIO_puts(out, "Hello\n");
}
//----------
client.c
//--------
#include "stdio.h"
#include "string.h"#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"int password_callback(char *buf, int size, int rwflag, void *userdata)
{
/* For the purposes of this demonstration, the password is "ibmdw" */printf("*** Callback function called\n");
strcpy(buf, "ibmdw");
return 1;
}int main()
{
SSL_CTX *ctx;
SSL *ssl;
BIO *bio, *abio, *out, *sbio;
char tmpbuf[1024];
int len;int (*callback)(char *, int, int, void *) = &password_callback;
printf("Secure Programming with the OpenSSL API, Part 4:\n");
printf("Serving it up in a secure manner\n\n");SSL_load_error_strings();
ERR_load_BIO_strings();
ERR_load_SSL_strings();
OpenSSL_add_all_algorithms();
SSL_library_init();printf("Attempting to create SSL context... ");
ctx = SSL_CTX_new(SSLv23_server_method());
if(ctx == NULL)
{
printf("Failed. Aborting.\n");
return 0;
}printf("\nLoading certificates...\n");
SSL_CTX_set_default_passwd_cb(ctx, callback);
if(!SSL_CTX_use_certificate_file(ctx, "certificate.pem", SSL_FILETYPE_PEM))
{
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
return 0;
}
if(!SSL_CTX_use_PrivateKey_file(ctx, "private.key", SSL_FILETYPE_PEM))
{
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
return 0;
}printf("Attempting to create BIO object... ");
bio = BIO_new_ssl(ctx, 0);
if(bio == NULL)
{
printf("Failed. Aborting.\n");
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
return 0;
}printf("\nAttempting to set up BIO for SSL...\n");
BIO_get_ssl(bio, &ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
abio = BIO_new_accept("4422");
BIO_set_accept_bios(abio, bio);printf("Waiting for incoming connection...\n");
if(BIO_do_accept(abio) <= 0)
{
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
BIO_free_all(bio);
BIO_free_all(abio);
return;
}if(BIO_do_accept(abio) <= 0)
{
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
BIO_free_all(bio);
BIO_free_all(abio);
return;
}out = BIO_pop(abio);
if(BIO_do_handshake(out) <= 0)
{
printf("Handshake failed.\n");
ERR_print_errors_fp(stdout);
SSL_CTX_free(ctx);
BIO_free_all(bio);
BIO_free_all(abio);
return;
}BIO_puts(out, "Hello\n");
//Read end
for(;;) {
len = BIO_read(sbio, tmpbuf, 1024);
if(len <= 0) break;
tmpbuf[len]='\0';
}
printf("%s", tmpbuf);
//Read end
if(strcmp(tmpbuf,"Hello\n")==0)
{
printf("Hello received sending user request\n");
BIO_puts(out, "Hello\n");
}
//-------
BIO_flush(out);
BIO_free_all(out);
BIO_free_all(bio);
BIO_free_all(abio);SSL_CTX_free(ctx);
}
BIO_flush(out);
BIO_free_all(out);
BIO_free_all(bio);
BIO_free_all(abio);SSL_CTX_free(ctx);
}
//-------
Проблема в том что со стороны клиента Hello получается принять и опознать
А со стороны сервера len = BIO_read(sbio, tmpbuf, 1024); возвращает ноль - тоесть на клиенте засовываю в out
буфер а он не а на сервере он просто не приходит.
Та конструкция которая в мануале вообще в буфер ничего не записывает ни на каких этапах вообще (( ни на сервере ни на клиенте.
http://openssl.org/docs/crypto/BIO_read.html
Вот описания функций - я не могу понять какие именно функции нужно использовать. (Сижу перевожу дальше)
Вобщем судя по всему надо переделывать кусок кода для чтения
//Read end
for(;;) {
len = BIO_read(sbio, tmpbuf, 1024);
if(len <= 0) break;
tmpbuf[len]='\0';
}
printf("%s", tmpbuf);
//Read end
Если добавить
//Read end
for(;;) {
len = BIO_read(sbio, tmpbuf, 1024);
printf("%d <------ should\n", BIO_should_retry(sbio));<---- Это
if(len <= 0) break;
tmpbuf[len]='\0';
}
printf("%s", tmpbuf);
//Read end
Возвращается 0 на обоих функциях(на сервере)
For example if a call to BIO_read() on a socket BIO returns 0 and BIO_should_retry() is false then the cause will be that the connection closed.
Значит соединение закрыто? Оно должно быть открыто может я как то не так использую BIO_should_retry()?
>так использую BIO_should_retry()?Дело еще например в том что логично предположить, что при удачном приеме (Если len > 0) - (Это на клиенте где прием удается) то функция
BIO_should_retry должна вернуть true(потому что соединение еще не закрыто) и ошибиться в том что это именно sbio(потому, что мы же все таки с него считываем) тоже сложно.(Хотя я пробовал и bio) один фиг возврящяется 0.
:S
Вобщем в итоге все упирается в то, что BIO_read на сервере возвращает -2 по документации If the return value is -2 then the operation is not implemented in the specific BIO type.
И вот тут тупик. На клиенте функция отрабатывает.P.S. Если я опять по вашему мнению спираю всю мысленную работу на вас - вы хоть отпишите(Даже сообщения ты студент, ты пень, кури маны только приветвтвуются)
>Вобщем в итоге все упирается в то, что BIO_read на сервере возвращает
>-2 по документации If the return value is -2 then the
>operation is not implemented in the specific BIO type.
>И вот тут тупик. На клиенте функция отрабатывает.
>
>P.S. Если я опять по вашему мнению спираю всю мысленную работу на
>вас - вы хоть отпишите(Даже сообщения ты студент, ты пень, кури
>маны только приветвтвуются)почитай:
http://www.linuxjournal.com/article/4822
http://www.linuxjournal.com/article/5487на ibm.com есть 3 статьи по программированию.
Спасибо за ответ - хороший материал.
Прочитал первую статью с горем пополам(С английским все плохо) Интересно но много букв и другой подход нежели на ibm.com - (В том числе и то, что например в этих статьях они вообще не используют bio_read).
Я их конечно дочитаю эти статьи чтобы понять в чем может быть проблема, но код я их использовать не буду. Тот код что выше это код взятый с openssl.org и исправленный немного(В первоначальном варианте он нерабочий) - сейчас уже почти все работает за исключением того что я не могу прочитать на сервере входящее сообщение. И проанализированный со статьями на ibm.com (Очень доступные статьи) я с этих статей стырил код чтения - записи - с анализом ошибки и с повтором. - В коде с openssl.org он прекрасно себя чувствует при передаче с сервера на клиент а наоборот - нет - такая же в общем история.
//Write begin
printf("Sending Hello server\n");
strcpy(tmpbuf, "Hello server\n");
for(;;)
{
if(BIO_write(out, tmpbuf, strlen(tmpbuf)) <= 0)
{
if(! BIO_should_retry(out))
{
printf("Write is crashed\n");
return 0;
}
continue;
}
break;
}
// Write end
//Read begin
for(;;)
{
len = BIO_read(sbio, tmpbuf, sizeof(tmpbuf));
if(len == 0)
{
printf("Server is close connection\n");
return 0;
}
else if(len < 0)
{
if(! BIO_should_retry(sbio))
{
printf("Read is crashed %d\n",len);
return 0;
}
continue;
}
break;
}
printf("[%s] --- [%d] \n",tmpbuf, strlen(tmpbuf));
//Read end
>Спасибо за ответ - хороший материал.
>Прочитал первую статью с горем пополам(С английским все плохо) Интересно но много
>букв и другой подход нежели на ibm.com - (В том числе
>и то, что например в этих статьях они вообще не используют
>bio_read).
>Я их конечно дочитаю эти статьи чтобы понять в чем может быть
>проблема, но код я их использовать не буду. Тот код что
>выше это код взятый с openssl.org и исправленный немного(В первоначальном варианте
>он нерабочий) - сейчас уже почти все работает за исключением тогособственно не понятно как он у вас работает, потому как в вашем клиенте нет главного, а именно попытки соединиться с сервером.
Прошу прощения я не правильно вставил код.
Вобщем почитал я тут поэксперементировал немного - некоторые вещи прояснились переделал код - в общем я в обе стороны могу передавать, но возникла следующая трудность:
Код подкючения и тд и тп я писать не буду - он рабочий осталость только понять как работают BIO_read + BIO_write вобщем
Идея следующая - код записи и чтения везде одинаковый на одной стороне считать а потом записать а на втором конце соответственно наоборот.
Получается следующая картина:
./send
Sending Hello server
End writing
lets reading
Before read./recv
Before readЭто означает то, что функция write отработала программа пошла дальше читать, а на другом конце read не получила ничего. - Но прикол в следующем если убрать код чтения из send. - Он будет отмечен внизу, read
получит свой Hello server.
$./recv
Before read
[13]<-----
[Hello client
] --- [13]
End reading
lets writing
Sending Hello server
End writing$ ./send
Sending Hello server
End writing
lets reading- И еще один момент - read отрабатывает после sleep на send. Это блин почему так может получиться? Складыавется такое чувство что данные передаются когда соединение завершается. - Странно не правда ли?
Код на одном конце:(recv.c)
//Read begin
for(;;)
{
printf("Before read\n");
len = BIO_read(sbio, tmpbuf, sizeof(tmpbuf));
printf("[%d]<-----\n",len);
if(len == 0)
{
printf("Server is close connection\n");
return 0;
}
else if(len < 0)
{
if(! BIO_should_retry(sbio))
{
printf("Read is crashed %d\n",len);
return 0;
}
continue;
}
tmpbuf[len]=0;
break;
}
printf("[%s] --- [%d] \n",tmpbuf, strlen(tmpbuf));
//Read end
printf("End reading\n");
BIO_flush(sbio);
sleep(5);
printf("lets writing\n");
//Write begin
printf("Sending Hello server\n");
strcpy(tmpbuf, "Hello client\n");
for(;;)
{
if(BIO_write(sbio, tmpbuf, strlen(tmpbuf)) <= 0)
{
if(! BIO_should_retry(sbio))
{
printf("Write is crashed\n");
return 0;
}
continue;
}
break;
}
// Write end
printf("End writing\n");
___________________________А вот на другом__________________________________________(send.c)//Write begin
printf("Sending Hello server\n");
strcpy(tmpbuf, "Hello client\n");
for(;;)
{
if(BIO_write(sbio, tmpbuf, strlen(tmpbuf)) <= 0)
{
if(! BIO_should_retry(sbio))
{
printf("Write is crashed\n");
return 0;
}
continue;
}
break;
}
// Write end
printf("End writing\n");
sleep(5);
printf("lets reading\n");
//Read begin <-----------------------
for(;;)
{
printf("Before read\n");
len = BIO_read(sbio, tmpbuf, sizeof(tmpbuf));
printf("[%d]<-----\n",len);
if(len == 0)
{
printf("Server is close connection\n");
return 0;
}
else if(len < 0)
{
if(! BIO_should_retry(sbio))
{
printf("Read is crashed %d\n",len);
return 0;
}
continue;
}
tmpbuf[len]=0;
break;
}
printf("[%s] --- [%d] \n",tmpbuf, strlen(tmpbuf));
//Read end
printf("End reading\n");
BIO_flush(sbio);<--------------------------------------
Ну вот я уже можно сказать скурил все маны оказалось что
int BIO_read(BIO *b, void *buf, int len);
Пытается прочесть из объекта b len байт данных в буфер buf. Возвращает количество
прочитанных байт.
- И будет пытаться пока соединение не завершится(Поэтому данные передавались в конце соединения - соединение рвется BIO_read выходит из цикла и показывает что получла) в отличие от
int BIO_gets(BIO *b, char *buf, int size);
Для большинства типов BIO выполняет операцию, аналогичную fgets — читает из b в buf
до ближайшего конца строки, но не более size байт.
Тоесть функция read ждет а gets не ждет. - Поскольку я не знаю сколько мне должно придти (параметр len мне узнать не откуда) функция gets выглядит более предпочтительно - НО! Функция BIO_set_conn_hostname которая определяет объект ввода вывода не поддерживает BIO_gets
Connect BIOs support BIO_puts() but not BIO_gets().
Как мне быть? Куда смотреть теперь?
Много несколько вариантов.
1. изменить свой протокол добавив туда посылку размера сообщения
2. использовать буферизованный ввод при помощи BIO_f_buffer
3. использовать nonblocking io на основе select в комбинации с BIO_should_retry