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

那怎么了?任何人 ?

4

2 回答 2

2

恐怕您不了解 GIO 是什么以及做什么,并试图将它与传统select()循环混合。在您当前的代码中,GIO 只会查看您在g_io_add_watch(in_handle,G_IO_IN|G_IO_OUT,(GIOFunc)network_deal_api,unit);. 它不使用fd_set结构。

当您接受每个连接时,您必须使用 GIO API 创建一个新GIOChannelg_io_channel_unix_new()并使用g_io_add_watch().

GIO 正在维护集合并在其事件循环中为您完成所有繁琐的工作,当 aGIOChannel具有您在调用中指定的条件时通知您g_io_add_watch()

(编辑更清楚)

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

于 2011-03-13T18:46:20.230 回答
0

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

于 2011-03-13T18:22:46.190 回答