2010-07-29 234 views
0

我試圖使用OpenSSL(錢德拉)從網絡安全重現的例子。該方案由client.cserver.ccommon.hcommon.c組成。 client.c僅在端口6012上創建與服務器的連接,並從stdin讀取數據,然後將這些數據發送到服務器。 server.c從套接字讀取數據並將其寫回stdout在pthread_create失敗,返回-1(或4294967295)

問題是,server.c總是卡在if(BIO_do_accept(acc) <= 0)在62行,永遠不會從client.c發送數據,它運行得很好。我後來發現問題是,第66行的pthread_create(...)(定義爲common.h中的THREAD_CREATE(...))失敗,它返回4294967295。由於THREAD_CREATE(...)失敗,程序永遠無法在server_thread(...)中運行do_server_loop,這就解釋了爲什麼服務器從未從客戶端獲取數據。

我應該如何解釋從pthread_create的返回值,我應該如何解決呢? PS。我後來用strerror轉換4294967295,它返回「未知錯誤」。

任何幫助將不勝感激!

////////////////////////////////////////////// ////

這裏是server.c

#include "common.h" 
void do_server_loop(BIO *conn) 
{ 
    int err, nread; 
    char buf[80]; 

    do 
    { 
     fprintf(stderr, "server_loop executed.\n"); 
     for(nread = 0; nread < sizeof(buf); nread += err) 
     { 
      err = BIO_read(conn, buf + nread, sizeof(buf) - nread); 
      if(err <= 0){ 
       break; 
      } 
     } 
     fwrite(buf, 1, nread, stdout); 
    } 
    while (err > 0); 
} 

void THREAD_CC server_thread(void *arg) 
{ 
    fprintf(stderr, "server_thread(void *arg) executed.\n"); 
    BIO *client = (BIO *)arg; 
#ifndef WIN32 
    pthread_detach(pthread_self()); 
#endif 
    fprintf(stderr, "Connection opened.\n"); 
    do_server_loop(client); 
    fprintf(stderr, "Connection closed.\n"); 

    BIO_free(client); 
    ERR_remove_state(0); 
#ifdef WIN32 
    _endthread(); 
#else 
    return 0; 
#endif 
} 


int main(int argc, char *argv[]) 
{ 
    BIO  *acc, *client; 
    int thread_create_result; 
    THREAD_TYPE tid; 

    init_OpenSSL(); 

    acc = BIO_new_accept(PORT); 
    if(!acc){ 
     int_error("Error creating server socket"); 
    } 

    if(BIO_do_accept(acc) <= 0){ 
     int_error("Error binding server socket"); 
    } 
    for(;;) 
    { 
     if(BIO_do_accept(acc) <= 0){ 
      int_error("Error accepting connection"); 
     } 
     client = BIO_pop(acc); 
     thread_create_result = THREAD_CREATE(tid, server_thread, client); 
     if(thread_create_result != 0){ 
      fprintf(stderr, "THREAD_CREATE failed! returns: %s.\n", \ 
              strerror(thread_create_result)); 
      fprintf(stderr, "thread_create_result has the value: %u.\n", \ 
              thread_create_result); 
      exit(-1); 
     } 
    } 

    BIO_free(acc); 
    return 0; 
} 

這裏是common.h

#include <errno.h> 
#include <fcntl.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <netinet/tcp.h> 
#include <openssl/bio.h> 
#include <openssl/err.h> 
#include <openssl/hmac.h> 
#include <openssl/objects.h> 
#include <openssl/rand.h> 
#include <openssl/ssl.h> 
#include <openssl/x509.h> 
#include <openssl/x509v3.h> 
#include <signal.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <strings.h> 
#include <sys/socket.h> 
#include <sys/time.h> 
#include <sys/types.h> 
#include <unistd.h> 


#ifndef WIN32 
#include <pthread.h> 
#define THREAD_CC * 
#define THREAD_TYPE   pthread_t 
#define THREAD_CREATE(tid, entry, arg) pthread_create(&(tid), NULL, \ 
            (entry), (arg)) 
#else 
#include <windows.h> 
#include <process.h> 
#define THREAD_CC    __cdecl 
#define THREAD_TYPE   DWORD 
#define THREAD_CREATE(tid, entry, arg) do { _beginthread((entry), 0, (arg));\ 
         (tid) = GetCurrentThreadId();\ 
         } while (0) 
#endif 

#define PORT "6012"  //port 
#define SERVER "10.1.251.24" //server address 
#define CLIENT "10.1.21.46" //client address 

#define int_error(msg) handle_error(__FILE__, __LINE__, msg) 
void handle_error(const char *file, int lineno, const char *msg); 

void init_OpenSSL(void); 

的Makefile:

CC = gcc 
OPENSSLDIR = /usr/local/ssl 
#CFLAGS = -g -Wall -W -I${OPENSSLDIR}/include -O2 -D_REENTRANT -D__EXTENSIONS__ 
CFLAGS = -g -Wall -W -I${OPENSSLDIR}/include -O2 

RPATH = -R${OPENSSLDIR}/lib 
#LD = ${RPATH} -L${OPENSSLDIR}/lib -lssl -lcrypto -lsocket -lnsl -lpthread 
LD = -L${OPENSSLDIR}/lib -lssl -lcrypto -lsocket -lnsl -pthread 

OBJS = common.o 

PROGS = server 

all: ${PROGS} 

server: server.o ${OBJS} 
     ${CC} server.o ${OBJS} -o server ${LD} 


clean:; 
     ${RM} ${PROGS} *.ln *.BAK *.bak *.o 
+0

確定返回值是在pthread_create?我想知道你是否使用了-DWIN32作爲它的#ifndef。 – 2010-07-29 14:44:38

+0

是的,我確定4294967295是從pthread_create返回的,後來我使用strerror轉換錯誤號並得到「未知錯誤」。我不認爲我用-DWIN32 ... – 2010-07-30 05:43:19

回答

0

在鏈接命令行上添加-D_REENTRANT上編譯命令線和-lpthread-D_REENTRANT會告訴C/C++庫,你的程序是多線程模式和-lpthread只加載共享庫libpthread.so在運行時。我發現這在William Garrison's POSIX threads tutorialthis link

這裏是Makefile中:

CC = gcc 
OPENSSLDIR = /usr/local/ssl 
CFLAGS = -g -Wall -W -I${OPENSSLDIR}/include -O2 -D_REENTRANT -D__EXTENSIONS__ 

RPATH = -R${OPENSSLDIR}/lib 
LD = ${RPATH} -L${OPENSSLDIR}/lib -lssl -lcrypto -lsocket -lnsl -lpthread 

OBJS = common.o 

PROGS = server 

all: ${PROGS} 

server: server.o ${OBJS} 
     ${CC} server.o ${OBJS} -o server ${LD} 


clean:; 
     ${RM} ${PROGS} *.ln *.BAK *.bak *.o 
2

變化

if(thread_create_result = !0){ 

if(thread_create_result != 0){ 

此外,你可以使用strerror功能錯誤代碼轉換爲人類可讀的形式。

+0

@ adf88編譯:謝謝!我更新了我的代碼並添加了「fprintf(stderr,」THREAD_CREATE失敗!返回:%s。\ n「,strerror(thread_create_result));」在線68.以下是程序返回的內容: THREAD_CREATE失敗!返回:未知錯誤。 thread_create_result的值爲:4294967295. – 2010-07-30 05:27:58

+0

@ adf88:我檢查了pthread_create列出的錯誤代碼,但找不到我得到的那個。謝謝! – 2010-07-30 05:32:34

+0

4294967295只是-1的未簽名版本。 – 2010-07-30 05:44:04