g_io_channel + socket = 服务器,仍然只得到一个客户端?用C语言

发布于 2024-10-20 20:53:00 字数 2808 浏览 0 评论 0原文

各位, 这里是我的代码:

#include <glib.h>
#include <gio/gio.h> // gio channel

#include <sys/socket.h> //socket();
#include <netdb.h> // structure

#include <stdio.h> // printf

void deal(GIOChannel *in, GIOCondition condition, gpointer data)
{
    struct sockaddr_storage income;

    int insock = g_io_channel_unix_get_fd(in);
    socklen_t income_len = sizeof(income);
    int newsock = accept(insock, (struct sockaddr*)&income, &income_len );
    if(newsock == -1)
    {
        printf("failure on newsock\n");
    }

    char buff[128];

    int recv_total = 0;
    int recv_byte = 128;
    int recv_sizing;

    while (recv_total < recv_byte ){

    recv_sizing = recv(newsock,buff + recv_total,recv_byte,0);

    // breaking if recv_sizing = -1 assuming as error, 0 assuming as lost communication from client suddenly
    if(recv_sizing < 0 || recv_sizing == 0)
     {
         printf("connection lost or error while recv(); [ just guess ] number : %d \n",recv_sizing);
         break;
    }

    recv_byte -= recv_sizing;
    recv_total += recv_sizing;


    }


    buff[recv_total] = '\0';
    //recv_sizing = recv(newsock,buff,recv_byte,0);
    printf("data : %s\n",buff);

    close(newsock); // close immediate and look for another some1 new


}

int main()
{
    GIOChannel *in;


    struct sockaddr_in my;
    my.sin_addr.s_addr = INADDR_ANY;
    my.sin_family      = AF_INET;
    my.sin_port        = htons(3000);

    //socket initiate root socket
    int rsock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    //allow re-use address
    setsockopt(rsock,SOL_SOCKET,SO_REUSEADDR,(int*)1,sizeof(int));

    //binding
    bind(rsock,(struct sockaddr*)&my,sizeof(my));

    //listen
    listen(rsock,10);


    in = g_io_channel_unix_new(rsock);

    g_io_add_watch(in, G_IO_IN | G_IO_OUT | G_IO_HUP, (GIOFunc) deal, NULL);


    GMainLoop *loop = g_main_loop_new(NULL,FALSE); // pengganti while(1) ato gtk_main_loop
    g_main_loop_run(loop);
    return 0;
}

这是它的编译和运行方式:

$ gcc -o dengersocket_glib dengersocket_glib.c `pkg-config --cflags --libs glib-2.0`
$ ./dengersocket_glib 

客户端想要尝试发送:

$ echo wew | nc -v localhost 3000 
nc: connect to localhost port 3000 (tcp) failed: Connection refused
Connection to localhost 3000 port [tcp/*] succeeded!

服务器接收:

$ ./dengersocket_glib 
connection lost or error while recv(); [ just guess ] number : 0 
data : wew

接收正常,但是当另一个客户端尝试连接时:

$ echo dor | nc -v localhost 3000 
nc: connect to localhost port 3000 (tcp) failed: Connection refused
Connection to localhost 3000 port [tcp/*] succeeded!

服务器上没有任何反应,如何使服务器可以接受多个客户端?在这些情况下真的需要 fd_set 吗?

folks,
here ma code :

#include <glib.h>
#include <gio/gio.h> // gio channel

#include <sys/socket.h> //socket();
#include <netdb.h> // structure

#include <stdio.h> // printf

void deal(GIOChannel *in, GIOCondition condition, gpointer data)
{
    struct sockaddr_storage income;

    int insock = g_io_channel_unix_get_fd(in);
    socklen_t income_len = sizeof(income);
    int newsock = accept(insock, (struct sockaddr*)&income, &income_len );
    if(newsock == -1)
    {
        printf("failure on newsock\n");
    }

    char buff[128];

    int recv_total = 0;
    int recv_byte = 128;
    int recv_sizing;

    while (recv_total < recv_byte ){

    recv_sizing = recv(newsock,buff + recv_total,recv_byte,0);

    // breaking if recv_sizing = -1 assuming as error, 0 assuming as lost communication from client suddenly
    if(recv_sizing < 0 || recv_sizing == 0)
     {
         printf("connection lost or error while recv(); [ just guess ] number : %d \n",recv_sizing);
         break;
    }

    recv_byte -= recv_sizing;
    recv_total += recv_sizing;


    }


    buff[recv_total] = '\0';
    //recv_sizing = recv(newsock,buff,recv_byte,0);
    printf("data : %s\n",buff);

    close(newsock); // close immediate and look for another some1 new


}

int main()
{
    GIOChannel *in;


    struct sockaddr_in my;
    my.sin_addr.s_addr = INADDR_ANY;
    my.sin_family      = AF_INET;
    my.sin_port        = htons(3000);

    //socket initiate root socket
    int rsock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    //allow re-use address
    setsockopt(rsock,SOL_SOCKET,SO_REUSEADDR,(int*)1,sizeof(int));

    //binding
    bind(rsock,(struct sockaddr*)&my,sizeof(my));

    //listen
    listen(rsock,10);


    in = g_io_channel_unix_new(rsock);

    g_io_add_watch(in, G_IO_IN | G_IO_OUT | G_IO_HUP, (GIOFunc) deal, NULL);


    GMainLoop *loop = g_main_loop_new(NULL,FALSE); // pengganti while(1) ato gtk_main_loop
    g_main_loop_run(loop);
    return 0;
}

these is how it get compiled and running :

$ gcc -o dengersocket_glib dengersocket_glib.c `pkg-config --cflags --libs glib-2.0`
$ ./dengersocket_glib 

the client wanna try to send :

$ echo wew | nc -v localhost 3000 
nc: connect to localhost port 3000 (tcp) failed: Connection refused
Connection to localhost 3000 port [tcp/*] succeeded!

the server receiving :

$ ./dengersocket_glib 
connection lost or error while recv(); [ just guess ] number : 0 
data : wew

receiving ok, but when another client trying to connecting :

$ echo dor | nc -v localhost 3000 
nc: connect to localhost port 3000 (tcp) failed: Connection refused
Connection to localhost 3000 port [tcp/*] succeeded!

nothing happen on server, how to make server could accept more than one client ? do fd_set really needed on these case ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

素手挽清风 2024-10-27 20:53:00

GIOFunc 类型返回 gboolean,而不是 void。您可以通过在将函数注册为回调时将其转换为 GIOFunc 来解决这个问题。

由于您的函数不返回任何内容,因此调用它的 glib 代码可能会将“FALSE”视为函数的返回值。 Glib 中的 FALSE 意味着“我不再需要监视此事件源”,因此当您的主循环仍在运行时(您从不调用 g_main_loop_quit()),它不再监视您的套接字。

正确实施 GIOFunc,您的问题可能就会消失。

The type GIOFunc returns gboolean, not void. You're working around that by casting your function to GIOFunc when registering it as a callback.

Since your function doesn't return anything, the glib code calling it probably sees "FALSE" as the return value of the function. FALSE in glib means "I don't need to monitor this event source anymore", so while youre main loop is still running (you never call g_main_loop_quit()), it is not monitoring your socket anymore.

Implement GIOFunc correctly and your problem will probably go away.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文