共享库函数在第一次打开后正常工作



我正在c中创建一个websocket服务器,因为将服务器关闭,重新编译它,并再次运行它对服务器应用程序应该做的事情适得其反,我正在寻找动态加载我的函数的方法,以便我可以保持主服务器应用程序运行,同时能够更改/创建将在其中使用的新函数。我创建了一个函数,它允许我按名称和正确的参数调用函数,就像你调用一个普通的函数一样,但是当我第二次调用它时,它不会做同样的事情,第二次我动态调用它。要按步骤列出我的问题,请考虑以下情况:

情况1

  1. 启动服务器应用程序而不动态调用sendMessage
  2. 通过浏览器连接websocket服务器
  3. 连接成功后向服务器发送消息(我使用Hello World)
  4. 服务器回显客户端发送的消息。
  5. 再次向服务器发送相同的消息
  6. 服务器将再次回显消息。(这是当服务器sendMessage函数没有动态加载
  7. 重复步骤5和6不会导致客户端断开连接。

现在是使用动态版本的服务器sendMessage函数来回显客户端消息的情况。

情况2

  1. 启动服务器应用程序,同时允许使用loadFunction调用sendMessage。
  2. 通过浏览器连接websocket服务器
  3. 连接成功后向服务器发送消息(我再次使用Hello World)
  4. 服务器将回显客户端发送的消息。
  5. 再次向服务器发送相同的消息
  6. 这次服务器不回显客户端发送的消息。
  7. 在第一个消息之后发送更多消息最终将导致连接结束(这就是我遇到问题的地方

情况1是当我的函数sendMessage被正常调用时(不是通过loadFunction),而情况2是我用loadFunction调用替换sendMessage,该调用加载持有sendMessage的库,将其分配给位置函数变量(见代码)并像往常一样调用函数。

我认为问题在于sendMessage中的写函数,当我动态加载它。但是,当我不动态加载它时,这个函数可以完美地工作,这对我来说很奇怪。

我的问题是为什么我的sendMessage函数的操作方式与我正常调用它和动态调用它的时候不同?下面是两种情况下的一些代码和输出

sendMessage.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include "include/structs.h"
//#include "include/functions.h"
/*
 * sendMessage: this function is used then we want to send message (s)
 *              of length (len) from the server to a client (sock)
 *
 * ARGUMENTS
 * sock:    the socket where we want the message to go
 * s:       A string containing the message we want to send
 * len: the length of the string s
 */
void *sendMessage(int sock, char *s, int len) {
    int frameCount;
    uint16_t len16;
    char frame[10];
    char *reply =   malloc(sizeof(char) * (len + 8));
    frame[0] =  'x81';
    if (len <= 125) {
        frame[1] = len;
        frameCount = 2;
    } else if (len >= 126 && len <= 65535) {
        frame[1] = 126;
        len16 = htons(len);
        memcpy(frame + 2, &len16, 2);
        frameCount = 4;
    } else {
        frame[1] = 127;
        //NOTE: HAVE NOT FULLY CONFIGURED A MESSAGE OF THIS LENGTH (TODO)
        //frame[2] = (char)( ((char)len >> 56) & (char)255 );
        //frame[3] = (char)( ((char)len >> 48) & (char)255 );
        //frame[4] = (char)( ((char)len >> 40) & (char)255 );
        //frame[5] = (char)( ((char)len >> 32) & (char)255 );
        //frame[6] = (char)( ((char)len >> 24) & (char)255 );
        frame[7] = (char)( ((char)len >> 16) & (char)255 );
        frame[8] = (char)( ((char)len >> 8) & (char)255 );
        frame[9] = (char)( ((char)len) & (char)255 );
        frameCount = 10;
    }//END IF
    memcpy(reply, frame, frameCount);
    memcpy(reply + frameCount, s, len);
    //printf("sock: %dts: %stlen: %dn", sock, s, len);
    if (write(sock, reply, strlen(reply)) <= 0) {
        printf("nnWE ARE NOT WRITING!!nn");
    } else {
        //printf("we did writen");
    }//END IF
    free(reply);
    reply = NULL;
    return NULL;
}//END FUNCTION

loadFunction.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include "include/functions.h"
int checkForError(char *error) {
    if (error != NULL) {
        printf("ERROR: %sn", error);
        exit(EXIT_FAILURE);
    }//END IF
    return 0;
}//END IF
void * loadFunction(char *func, void ** args) {
    void *handle;
    //void * (*alterStruct)(int sock, char *action);
    int filenameLength;
    char * filename;
    //void *(*funcPtr);

    filenameLength = strlen("lib/lib") + strlen(func) + strlen(".dll");
    filename = malloc(sizeof(char) * (filenameLength + 1));
    strcpy(filename, "lib/lib");
    strcat(filename, func);
    strcat(filename, ".dll");
    handle = dlopen(filename, RTLD_LAZY);
    free(filename);
    if (!handle) {
        checkForError(dlerror());
    }//END IF
    dlerror();
    if (strncmp(func, "sendMessage", strlen(func)) == 0) {
        void * (*funcPtr)(int, char *, int);
        //*(void **) (&funcPtr) = dlsym(handle, func);
        funcPtr = (void *)dlsym(handle, func);
        checkForError(dlerror());
        (*funcPtr)((int)args[0], (char *)args[1], (int)args[2]);
        //free(*(void **)(&funcPtr));
        //*(void **) (&funcPtr) = NULL;
    }// else if (strncmp(func, "alterStruct", strlen(func)) == 0) {
        //void * (*funcPtr)(int sock, char *action);
    //} else if (strncmp(func, "execute", strlen(func)) == 0) {
        //void * (*funcPtr)(const char *command, clientStruct s, FILE **in, FILE **out, FILE **err);
    //} else {
        //void * (*funcPtr)(int sock, char *s, int len);
    //}//END IF
    dlclose(handle);
    handle = NULL;
    return NULL;

    return NULL;
}//END loadFunction

如果你需要更多的代码来解决这个问题,我可以在GitHub上访问这里(动态分支是可以找到问题的地方)

另外,我正在使用Cygwins的GNU gcc编译器(我从来没有编译上的问题)来编译我的应用程序和库,所以我可能无法访问某些Linux命令(例如dlmopen)。也就是说,请不要说使用不同的编译器,因为到目前为止我还没有遇到其他问题,我也不打算改变我编译代码的方式。

我没有记录我用来编译loadFunction中使用的libsendMessage.dll的命令。您可以使用以下命令

获取它
gcc -c -fPIC sendMessage.c
mv sendMessage.o objects/sendMessage.o
gcc -shared -o lib/libsendMessage.dll objects/sendMessage.o libfunctions.c

提前感谢。

我已经弄明白我的问题了,这是一个相当奇怪的问题。

当我使用我的动态方法i printf测试sendMessage函数时,确切地说,通过套接字发送的是什么,显然它正在发送正确的消息。然而,它也在loadFunction函数中从我的文件名变量发送字符,这对我来说很奇怪,在调用动态sendMessage的函数调用之前,当malloc ed,释放并设置为NULL时,内存地址可以访问sendMessage

<<p> 解决方案/strong>

在我用dlopen(filename, RTLD_LAZY)打开我的库之后,我使用memset(filename, '', filenameLength)将空字符写入文件名的内存地址,使字符串包含所有空字符,当作为字符访问时,这些字符计数为字符串的结束。

我不知道为什么我不得不在这个应用程序中使用memset这么多,但我知道它已经为我多次修复了字符串错误。

相关内容

  • 没有找到相关文章