我的C-Lua混合程序中的字符串连接

我无法弄清楚为什么发生这种情况,但它是,而且很奇怪。我正在酝酿一个服务器,以了解更多关于套接字编程和C-Lua API的知识,除了一个(不是很小)的打嗝外,它的工作原理都很好。我的C-Lua混合程序中的字符串连接

到目前为止,它所做的只是接受连接,并检查可读连接,然后读取它们。它将所读取的内容传递给特定于该连接的Lua状态的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”,那么s赢了“T成为:

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

而是:

"and then some stuff at the end.d. 

,我不能为我弄明白的生活为什么它这样做,这是具体到下面的代码中的问题,因为我能!我不会在一个简单的程序中重现它,但我不知道可能会导致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 ----------*/

回答:

因为您的's'包含通过telnet发送的换行符号或您使用的任何符号。从http://lua-users.org/wiki/StringTrim获得一个修剪实现,并使用s = 'You sent the string: "' .. trim(s) .. '" and then some stuff at the end.'或类似的东西。

更新:抱歉,这是回车的可能性要大得多。但无论如何,鉴于你的问题。

以上是 我的C-Lua混合程序中的字符串连接 的全部内容, 来源链接: utcz.com/qa/262240.html

回到顶部