gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 03:00:09 25 4
gpt4 key购买 nike

我不明白为什么会这样,但确实如此,而且很奇怪。我正在酝酿一个服务器来学习更多关于套接字编程和 C-Lua API 的信息,它工作得很好,除了一个(不是很轻微的)问题。

到目前为止,它所做的只是接受连接,检查可读连接,然后从中读取。它将读取的内容传递给处于特定于该连接的 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 won '成为:

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 - 我的 C-Lua 混合程序中的字符串连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12947336/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com