聊天套接字 + gio_channel 没有立即用 C 语言显示传入数据包?
大家请看下面的代码:
#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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(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,使用
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 ing_io_add_watch(in_handle,G_IO_IN|G_IO_OUT,(GIOFunc)network_deal_api,unit);
. It doesn't usefd_set
structures.You have to use the GIO API when you accept each connection creating a new
GIOChannel
withg_io_channel_unix_new()
and adding it usingg_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 theg_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 theIOChannel
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.我对 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 newlyaccept(2)
-ed socket?