聊天套接字 + gio_channel 没有立即用 C 语言显示传入数据包?

发布于 2024-10-21 17:54:29 字数 5165 浏览 6 评论 0原文

大家请看下面的代码:

#include <gio/gio.h>
#include <sys/socket.h> //socket();
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h>

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define RECV_SIZE_MODE 1024 // mmmm

    typedef struct _unit_
    {
        gint sockmax;
        fd_set client,client_tmp;
    } _unit;



gboolean network_deal_api(GIOChannel *in,GIOCondition condition, _unit *unit)
{
    struct sockaddr_storage income;

            unit->client_tmp = unit->client;


    gint i;

    //enum client
    gchar ip[INET_ADDRSTRLEN];
    guint port;

    //convert
    gint insock = g_io_channel_unix_get_fd(in);


    //prepare for new income
    socklen_t income_len = sizeof(income);
    gint newsock;

    //something come in
    char buffer_in[RECV_SIZE_MODE] = {0}; 
    gint recv_sizing;

    switch(condition)
    {
        case G_IO_IN:


        for(i=0; i <= unit->sockmax; i++)
        {

          if(FD_ISSET(i,&unit->client_tmp)) //something coming through handler inside client_tmp, we'll see if the socket has suppose to be someone own
          {
              printf("process on socket number : %d\n",i);
                    if(i == insock) // if handler of socket(); then create new accept handler, if these is a handler of accept();, then else which mean 'incoming data'
                    {
                        newsock = accept(insock,(struct sockaddr*)&income, &income_len);
                        if(newsock == -1)
                        {
                            printf("failure once getting new socket\n");
                            return FALSE;
                        }
                        else
                        {
                            FD_SET(newsock, &unit->client);
                            if(newsock > unit->sockmax)
                            {
                                unit->sockmax = newsock;
                            }

                        inet_ntop(income.ss_family,&((struct sockaddr_in*)&income)->sin_addr,ip,INET_ADDRSTRLEN);
                        port = htons(((struct sockaddr_in*)&income)->sin_port);
                        printf("connected to : %s:%d on socket : %d\n",ip,port,newsock);
                        }



                    }
                    else
                    {


                        if(recv_sizing = recv(i,buffer_in,RECV_SIZE_MODE,0) <= 0)
                        {
                            if(recv_sizing == 0)
                            {
                                printf("socket %d hung up\n",i);
                            }
                            if(recv_sizing == -1)
                            {
                                perror("recv");
                            }
                            close(i);
                            FD_CLR(i,&unit->client);
                        }
                        buffer_in[recv_sizing-1] = '\0';
                        printf("data in : %s length : %d\n",buffer_in,strlen(buffer_in));

                    }
            }
        }
        break;

    }
}

int main()
{


    _unit *unit = (_unit*)malloc(sizeof(_unit));

    struct sockaddr_in my; // set my network device info
    gint rootsock;         // handle the root socket

    GIOChannel *in_handle;
    guint in_handle_watching;       // whether the watching event intend to remove

     FD_ZERO(&unit->client); // initiate
     FD_ZERO(&unit->client_tmp);






    //let construct a server

    //socket
    rootsock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    //binding
    memset(&my,0,sizeof(my));
    my.sin_addr.s_addr = INADDR_ANY;
    my.sin_family      = AF_INET;
    my.sin_port        = htons(1111);
    bind(rootsock,(struct sockaddr*)&my,sizeof(my));

    //set the queue, let say for commonly situation 10
    listen(rootsock,10);

    FD_SET(rootsock,&unit->client);

    unit->sockmax = rootsock; //so far its this one


     in_handle = g_io_channel_unix_new(rootsock); // handed socket to channel

    in_handle_watching = g_io_add_watch(in_handle,G_IO_IN|G_IO_OUT,(GIOFunc)network_deal_api,unit);

    printf("server listening on : %d\n",ntohs(my.sin_port));
    printf("look forward for any new income connection\n");

    GMainLoop *loop = g_main_loop_new(NULL,FALSE);
    g_main_loop_run(loop);

    free(unit);

    return 0;
    }

并编译并运行:

$ gcc -o multiplechat_gio multiplechat_gio.c `pkg-config --libs --cflags gio-2.0`
$ ./multiplechat_gio 
  server listening on : 1111
  look forward for any new income connection

有人远程登录到它:

$ telnet localhost 1111
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
tes
aja
deh
^C

为什么服务器不显示数据包(并且仅在其他人连接到服务器时显示数据包)?

$ ./multiplechat_gio 
server listening on : 1111
look forward for any new income connection
process on socket number : 3
connected to : 127.0.0.1:48814 on socket : 4

那怎么了? 有人吗?

folks please see following code :

#include <gio/gio.h>
#include <sys/socket.h> //socket();
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h>

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define RECV_SIZE_MODE 1024 // mmmm

    typedef struct _unit_
    {
        gint sockmax;
        fd_set client,client_tmp;
    } _unit;



gboolean network_deal_api(GIOChannel *in,GIOCondition condition, _unit *unit)
{
    struct sockaddr_storage income;

            unit->client_tmp = unit->client;


    gint i;

    //enum client
    gchar ip[INET_ADDRSTRLEN];
    guint port;

    //convert
    gint insock = g_io_channel_unix_get_fd(in);


    //prepare for new income
    socklen_t income_len = sizeof(income);
    gint newsock;

    //something come in
    char buffer_in[RECV_SIZE_MODE] = {0}; 
    gint recv_sizing;

    switch(condition)
    {
        case G_IO_IN:


        for(i=0; i <= unit->sockmax; i++)
        {

          if(FD_ISSET(i,&unit->client_tmp)) //something coming through handler inside client_tmp, we'll see if the socket has suppose to be someone own
          {
              printf("process on socket number : %d\n",i);
                    if(i == insock) // if handler of socket(); then create new accept handler, if these is a handler of accept();, then else which mean 'incoming data'
                    {
                        newsock = accept(insock,(struct sockaddr*)&income, &income_len);
                        if(newsock == -1)
                        {
                            printf("failure once getting new socket\n");
                            return FALSE;
                        }
                        else
                        {
                            FD_SET(newsock, &unit->client);
                            if(newsock > unit->sockmax)
                            {
                                unit->sockmax = newsock;
                            }

                        inet_ntop(income.ss_family,&((struct sockaddr_in*)&income)->sin_addr,ip,INET_ADDRSTRLEN);
                        port = htons(((struct sockaddr_in*)&income)->sin_port);
                        printf("connected to : %s:%d on socket : %d\n",ip,port,newsock);
                        }



                    }
                    else
                    {


                        if(recv_sizing = recv(i,buffer_in,RECV_SIZE_MODE,0) <= 0)
                        {
                            if(recv_sizing == 0)
                            {
                                printf("socket %d hung up\n",i);
                            }
                            if(recv_sizing == -1)
                            {
                                perror("recv");
                            }
                            close(i);
                            FD_CLR(i,&unit->client);
                        }
                        buffer_in[recv_sizing-1] = '\0';
                        printf("data in : %s length : %d\n",buffer_in,strlen(buffer_in));

                    }
            }
        }
        break;

    }
}

int main()
{


    _unit *unit = (_unit*)malloc(sizeof(_unit));

    struct sockaddr_in my; // set my network device info
    gint rootsock;         // handle the root socket

    GIOChannel *in_handle;
    guint in_handle_watching;       // whether the watching event intend to remove

     FD_ZERO(&unit->client); // initiate
     FD_ZERO(&unit->client_tmp);






    //let construct a server

    //socket
    rootsock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    //binding
    memset(&my,0,sizeof(my));
    my.sin_addr.s_addr = INADDR_ANY;
    my.sin_family      = AF_INET;
    my.sin_port        = htons(1111);
    bind(rootsock,(struct sockaddr*)&my,sizeof(my));

    //set the queue, let say for commonly situation 10
    listen(rootsock,10);

    FD_SET(rootsock,&unit->client);

    unit->sockmax = rootsock; //so far its this one


     in_handle = g_io_channel_unix_new(rootsock); // handed socket to channel

    in_handle_watching = g_io_add_watch(in_handle,G_IO_IN|G_IO_OUT,(GIOFunc)network_deal_api,unit);

    printf("server listening on : %d\n",ntohs(my.sin_port));
    printf("look forward for any new income connection\n");

    GMainLoop *loop = g_main_loop_new(NULL,FALSE);
    g_main_loop_run(loop);

    free(unit);

    return 0;
    }

and compiled and run :

$ gcc -o multiplechat_gio multiplechat_gio.c `pkg-config --libs --cflags gio-2.0`
$ ./multiplechat_gio 
  server listening on : 1111
  look forward for any new income connection

someone telnet into it :

$ telnet localhost 1111
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
tes
aja
deh
^C

and why the server is not showing the packet (and show packet once another people connect to the server only) ?

$ ./multiplechat_gio 
server listening on : 1111
look forward for any new income connection
process on socket number : 3
connected to : 127.0.0.1:48814 on socket : 4

whats wrong then ?
anyone ?

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

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

发布评论

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

评论(2

撞了怀 2024-10-28 17:54:29

恐怕您不了解 GIO 是什么和做什么,并试图将其与传统的 select() 循环混合。在您当前的代码中,GIO 仅查看您在 g_io_add_watch(in_handle,G_IO_IN|G_IO_OUT,(GIOFunc)network_deal_api,unit); 中提供的原始文件描述符。它不使用fd_set结构。

当您接受每个连接时,您必须使用 GIO API,使用 g_io_channel_unix_new() 创建新的 GIOChannel 并使用 g_io_add_watch() 添加它。

GIO 正在维护该集合并在其事件循环中为您完成所有脏活,当 GIOChannel 满足您在 g_io_add_watch() 调用中指定的条件时通知您。

(经过编辑以使其更清楚)

另请注意 - g_io_add_watch() 的最后一个参数应该用于保存特定于添加的 IOChannel 的数据(您可以使用 malloc()当您接受连接时它)。这是您粘贴连接特定数据的地方,例如用户名或之前的状态等。

I'm afraid you're not understanding what GIO is and does, and are attempting to mix it with a traditional select() loop. In your current code, GIO is only ever looking at the original file descriptor you gave it in g_io_add_watch(in_handle,G_IO_IN|G_IO_OUT,(GIOFunc)network_deal_api,unit);. It doesn't use fd_set structures.

You have to use the GIO API when you accept each connection creating a new GIOChannel with g_io_channel_unix_new() and adding it using g_io_add_watch().

GIO is maintaining the set and doing all the dirty work for you in its event loop, notifying you when a GIOChannel has the condition you specify in the g_io_add_watch() call.

(Edited to make more clear)

Also note - the last argument to g_io_add_watch() is supposed to be used to hold data specific to the IOChannel added (you would malloc() it when you accept the connection) . This is where you stick connection specific data, like a username, or previous state, etc.

终陌 2024-10-28 17:54:29

我对 GIO 不太熟悉,但是您不应该在新的 accept(2) 套接字上调用 g_io_add_watch() 吗?

I'm not really familiar with the GIO, but shouldn't you call g_io_add_watch() on newly accept(2)-ed socket?

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