2012-10-18 1 views
1

왜 이런 일이 발생하는지 알 수는 없지만 이상한 일입니다. 나는 소켓 프로그래밍과 C-Lua API에 대해서 더 많은 것을 배우기 위해 서버를 양조하고 있는데, 하나의 (아주 사소한) 딸꾹질을 제외하고는 완벽하게 작동한다.내 C-Lua 하이브리드 프로그램 내에서 문자열 연결

지금까지는 연결을 허용하고 읽을 수있는 연결이 있는지 확인한 다음 해당 연결에서 읽습니다. 그것은 읽은 것을 루아 함수에 전달하여 그 연결에 특정한 루아 (Lua) 상태로 보낸다. 그런 다음 클라이언트에 되돌려 보내고 (서버용으로 출력한다).

어떤 이유로 문자열 연결이 실제로 이상하게 작동합니다. 나는 간단한 테스트 프로그램에서 그것을 재현 할 수 없기 때문에 어떤 원인인지 알지 못한다. 기본적으로, 여기 내 루아/state.lua 파일이 있습니다 :

function OnRead(...) 
    local s = table.concat({...}) 
    print(s) 
    s = 'You sent the string: "' .. s .. '" and then some stuff at the end.' 
    print(s) 
    send(s) 
end 

그럼 알다시피, 아주 간단합니다. 첫 번째 인쇄가 제대로 작동합니다. 그러나 일단 내가 연결하면, 마지막에있는 물건 (예를 들어, "그리고"마지막 물건 ")이 문자열의 시작 부분에 쓰여질 것입니다! 그래서 입력이"Hello World "문자열이면, 그것은이 일을 왜 내가 할 수있는대로, 다음 코드와 관련된 문제입니다

"and then some stuff at the end.d. 

그리고 나는 나의 그림 밖으로의 삶에 대한 작업을 수행 할 수 없습니다!

You sent the string: "Hello World." and then some stuff at the end. 

아니라이 '는 t이 될 작은 간단한 프로그램으로 재현 할 수는 없지만, Lua 스크립트가 무엇을 잘못 이상하게 만들지는 모르겠습니다.

#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <time.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <lua.h> 
#include <lualib.h> 
#include <lauxlib.h> 

#define SERVER_PORT 5000 

#define READ_OVERFLOW_SIZE_LIMIT 4098 /* maximum socket line length */ 
#define READ_BUFFER_SIZE 4098 
#define BUFFER_SIZE 1024 
#define SHORT_BUFFER_SIZE 64 


#define STATE_LUA_FILE "lua/state.lua" 
/* L_ prefix for Lua registry table keys */ 
#define L_CONNFD "server_connfd" 
/* G_ prefix for Lua global table keys */ 
#define G_ONREAD_HANDLER "OnRead" 

typedef struct node_t { 
    struct node_t *next; 
    struct node_t *prev; 
    int value; 
    lua_State *state; 
} ll_conn_t; 


/*----------------------------------------------------------------------------- 
* Appends a connection tuple to a linked list. Returns 0 on success, or a -1 
* on error. 
* If the connfd value is already present in the linked list, it will error. 
*---------------------------------------------------------------------------*/ 
int ll_conn_append(ll_conn_t *list, int value, lua_State *state) 
{ 
    ll_conn_t *temp; 
    for (temp = list; temp->next != NULL; temp = temp->next) 
    { 
     if (temp->next->value == value) 
      return -1; 
    } 
    temp->next = (ll_conn_t *)malloc(sizeof(ll_conn_t)); 
    temp->next->prev = temp; 
    temp->next->next = NULL; 
    temp->next->value = value; 
    temp->next->state = state; 
    list->value++; 
    return 0; 
} /*----- end of function ll_conn_append -----*/ 


/*----------------------------------------------------------------------------- 
* Creates a new linked list and returns a pointer to the new linked list. 
*---------------------------------------------------------------------------*/ 
ll_conn_t *ll_conn_create() 
{ 
    ll_conn_t *list = (ll_conn_t *)malloc(sizeof(ll_conn_t)); 
    list->next = NULL; 
    list->prev = NULL; 
    list->value = 0; 
    list->state = NULL; 
    return list; 
} /*----- end of function ll_conn_create -----*/ 


/*----------------------------------------------------------------------------- 
* Iterates over a linked list and completely frees up its memory. 
*---------------------------------------------------------------------------*/ 
void ll_conn_delete(ll_conn_t *list) 
{ 
    ll_conn_t *temp; 
    for (temp = list->next; temp != NULL; list = temp, temp = temp->next) 
    { 
     lua_close(list->state); 
     free(list); 
    } 
} /*----- end of function ll_conn_delete -----*/ 


/*----------------------------------------------------------------------------- 
* Searches for and removes the first occurrence of a specific connfd from a 
* linked list. Returns a boolean which indicates whether the value was found. 
*---------------------------------------------------------------------------*/ 
int ll_conn_remove(ll_conn_t *list, int value) 
{ 
    ll_conn_t *iter, *temp; 
    for (iter = list; iter->next != NULL; iter = iter->next) 
    { 
     temp = iter->next; 
     if (temp->value == value) 
     { 
      iter->next = temp->next; 
      if (temp->next != NULL) 
       temp->next->prev = iter; 
      lua_close(temp->state); 
      free(temp); 
      list->value--; 
      return 1; 
     } 
    } 
    return 0; 
} /*----- end of function ll_conn_remove -----*/ 


/*----------------------------------------------------------------------------- 
* lua_CFunction 
* Takes a string argument, and writes that string to this Lua state's socket 
* connection. 
*---------------------------------------------------------------------------*/ 
int luasend(lua_State *L) 
{ 
    int connfd, success, length; 
    lua_pushstring(L, L_CONNFD); 
    lua_rawget(L, LUA_REGISTRYINDEX); 
    connfd = (int)lua_tointegerx(L, -1, &success); 
    lua_pop(L, 1); 
    if (!success) 
    { 
     /* error! */ 
     lua_pushstring(L, "Socket connfd could not be converted to integer!"); 
     lua_error(L); 
    } 
    length = luaL_len(L, -1); 
    write(connfd, lua_tostring(L, -1), length); 
    lua_pop(L, 1); 
    return 0; 
} /*----- end of function luasend -----*/ 


/*----------------------------------------------------------------------------- 
* Takes as input a connected socket file descriptor and builds a new Lua 
* state for that socket. 
*---------------------------------------------------------------------------*/ 
lua_State *l_create_state(int connfd) 
{ 
    lua_State *L = luaL_newstate(); 
    luaL_openlibs(L); 
    lua_pushstring(L, L_CONNFD); 
    lua_pushinteger(L, connfd); 
    lua_rawset(L, LUA_REGISTRYINDEX); 
    lua_register(L, "send", *luasend); 
    luaL_dofile(L, STATE_LUA_FILE); 
    return L; 
} /*----- end of function l_create_state -----*/ 


/*----------------------------------------------------------------------------- 
* Reads from the Lua state's connection, and calls the Lua handler for each 
* line it encounters in the read buffer. 
*---------------------------------------------------------------------------*/ 
void l_read_conn(lua_State *L, int connfd) 
{ 
    static char buffer[READ_BUFFER_SIZE]; 
    int count = 1, i, start, overflow_count = 0, overflow_size = 0, len; 
    while (1) 
    { 
     ioctl(connfd, FIONREAD, &len); 
     if (len == 0) 
      break; 
     count = read(connfd, buffer, READ_BUFFER_SIZE); 
     if (count == -1) 
     { 
      /* TODO error handling */ 
      break; 
     } 
     if (count == 0) 
     { 
      /* EOF */ 
      break; 
     } 
     start = 0; 
     for (i = 0; i < count; i++) 
     { 
      if (buffer[i] != '\n') 
       continue; 
      if (!overflow_count) 
       lua_getglobal(L, G_ONREAD_HANDLER); 
      /* We won't be passing newlines to the handler. Otherwise, it would 
      * be 1 + i - start. */ 
      lua_pushlstring(L, buffer + start, i - start); 
      lua_call(L, 1, 0); 
      overflow_count = overflow_size = 0; 
      start = i + 1; 
     } 
     /* If there's bits in the buffer that aren't terminated with a newline, 
     * add it as overflow to the stack. 
     * NOTE: THIS IS A REALLY BAD IDEA !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 
     if (start < count) 
     { 
      if (!overflow_count) 
       lua_getglobal(L, G_ONREAD_HANDLER); 
      lua_pushlstring(L, buffer + start, count - start); 
      overflow_size += count - start; 
      overflow_count++; 
      /* let's include this check to make this a marginally less bad idea 
      * in order to soothe my OCD worries */ 
      if (overflow_size >= READ_OVERFLOW_SIZE_LIMIT) 
       break; 
     } 
    } 
    if (overflow_count) 
     lua_call(L, overflow_count, 0); 
} /*----- end of function l_read_conn -----*/ 


int main(int argc, char *argv[]) 
{ 
    int listenfd = 0, connfd = 0, maxfd = 0; 
    struct sockaddr_in serv_addr, conn_addr; 
    char sendBuff[BUFFER_SIZE]; 
    lua_State *L; 
    fd_set fds; 
    ll_conn_t *connections = ll_conn_create(); 
    /* iterators */ 
    ll_conn_t *temp; 
    int n; 
    unsigned int i, j; 

    listenfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (listenfd == -1) 
    { 
     /* TODO error handling */ 
    } 
    memset(&serv_addr, '0', sizeof(serv_addr)); 
    memset(sendBuff, '0', BUFFER_SIZE); 

    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    serv_addr.sin_port = htons(SERVER_PORT); 

    if (bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) 
    { 
     /* TODO error handling */ 
    } 

    if (listen(listenfd, 10) == -1) 
    { 
     /* TODO error handling */ 
    } 

    while (1) 
    { 
     FD_ZERO(&fds); 
     FD_SET(listenfd, &fds); 
     if (listenfd >= maxfd) 
      maxfd = listenfd + 1; 
     for (temp = connections->next; temp != NULL; temp = temp->next) 
      FD_SET(temp->value, &fds); 
     if ((n = select(maxfd, &fds, NULL, NULL, NULL)) > 0) 
     { 
      if (FD_ISSET(listenfd, &fds)) 
      { 
       i = sizeof(conn_addr); 
       connfd = accept(listenfd, (struct sockaddr *)&conn_addr, &i); 
       if (connfd < 0) 
       { 
        /* TODO error handling */ 
       } 
       L = l_create_state(connfd); /* create new state */ 
       if (ll_conn_append(connections, connfd, L) < 0) 
       { 
        /* TODO error handling */ 
       } 
       if (connfd >= maxfd) 
        maxfd = connfd + 1; 
       printf("New connection from %s.\n", 
         inet_ntoa(conn_addr.sin_addr)); 
      } 
      /* we do iteration this way so that we don't segfault!!! */ 
      for (temp = connections->next; temp != NULL;) 
      { 
       connfd = temp->value; 
       L = temp->state; 
       temp = temp->next; 
       if (FD_ISSET(connfd, &fds)) 
       { 
        /* check connection status */ 
        ioctl(connfd, FIONREAD, &j); 
        if (j == 0) 
        { 
         /* the socket should now be removed! */ 
         ll_conn_remove(connections, connfd); 
        } 
        else 
        { 
         /* read from connection */ 
         l_read_conn(L, connfd); 
        } 
       } 
      } 
     } 
     if (n < 0) 
     { 
      /* TODO error handling */ 
     } 
    } 
    return EXIT_SUCCESS; 
}  /*---------- end of function main ----------*/ 

답변

2

's'에 telnet이나 사용자가 사용하는 모든 문자가 포함되어 있기 때문에. http://lua-users.org/wiki/StringTrim에서 트림 구현 중 하나를 가져 와서 s = 'You sent the string: "' .. trim(s) .. '" and then some stuff at the end.' 또는 그와 비슷한 것을 사용하십시오.

업데이트 : 죄송합니다. 캐리지 리턴이 될 가능성이 훨씬 큽니다. 그러나 아무리해도, 당신의 질문에 대한 관점에서.

+0

고맙습니다. 그게 정확히 무엇을했는지. – Santiclause

관련 문제