社区
C语言
帖子详情
udp socket如何实时接受?
xhbpla
2006-07-19 04:49:55
在程序中,上层的数据收发通过udp进行,
问题是,在程序运行时,要监视下层数据什么时候到达,
然后就调用接受函数,
相当于要实现消息机制,收到数据时,有系统的函数通知,
或者调用 接受函数,而不是让接受函数循环等待.
这个用c ,怎么实现,是不是要什么回调函数,还是多线程之类的方法
...全文
465
16
打赏
收藏
udp socket如何实时接受?
在程序中,上层的数据收发通过udp进行, 问题是,在程序运行时,要监视下层数据什么时候到达, 然后就调用接受函数, 相当于要实现消息机制,收到数据时,有系统的函数通知, 或者调用 接受函数,而不是让接受函数循环等待. 这个用c ,怎么实现,是不是要什么回调函数,还是多线程之类的方法
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
16 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
xhbpla
2006-09-07
打赏
举报
回复
再顶,
估计搞个线程啥的
boot2006
2006-08-31
打赏
举报
回复
把他放在xinetd.d服务里,当有数据过来的时候自动启动程序,接收完毕,自动退出
zhxzhx
2006-08-30
打赏
举报
回复
顶起来
看来还是要用线程
zez
2006-08-23
打赏
举报
回复
while 1
select
Arthur_
2006-08-23
打赏
举报
回复
select 最好了
不然就是选折阻塞算法,不是很好
neustrong
2006-08-23
打赏
举报
回复
开个线程。
xhbpla
2006-08-23
打赏
举报
回复
再顶起来,
能不能搞个新任务,来出来UDP接受?
xhbpla
2006-07-21
打赏
举报
回复
网上找了一下:
Select()系统调用及文件描述符集fd_set的应用
在网络程序中,一个进程同时处理多个文件描述符是很常见的情况。select()系统调用可以使进程检测同时等待的多个I/O设备,当没有设备准备好时,select()阻塞,其中任一设备准备好时,select()就返回。
select()的调用形式为:
#include <sys/select.h>
#include <sys/time.h>
int select(int maxfd, fd_set *readfds, fd_set *writefds, fe_set *exceptfds, const struct timeval *timeout);
select的第一个参数是文件描述符集中要被检测的比特数,这个值必须至少比待检测的最大文件描述符大1;参数readfds指定了被读监控的文件描述符集;参数writefds指定了被写监控的文件描述符集;而参数exceptfds指定了被例外条件监控的文件描述符集。
参数timeout起了定时器的作用:到了指定的时间,无论是否有设备准备好,都返回调用。timeval的结构定义如下:
struct timeval{
long tv_sec; //表示几秒
long tv_usec; //表示几微妙
}
timeout取不同的值,该调用就表现不同的性质:
1.timeout为0,调用立即返回;
2.timeout为NULL,select()调用就阻塞,直到知道有文件描述符就绪;
3.timeout为正整数,就是一般的定时器。
select调用返回时,除了那些已经就绪的描述符外,select将清除readfds、writefds和exceptfds中的所有没有就绪的描述符。select的返回值有如下情况:
1.正常情况下返回就绪的文件描述符个数;
2.经过了timeout时长后仍无设备准备好,返回值为0;
3.如果select被某个信号中断,它将返回-1并设置errno为EINTR。
4.如果出错,返回-1并设置相应的errno。
系统提供了4个宏对描述符集进行操作:
#include <sys/select.h>
#include <sys/time.h>
void FD_SET(int fd, fd_set *fdset);
void FD_CLR(int fd, fd_set *fdset);
void FD_ISSET(int fd, fd_set *fdset);
void FD_ZERO(fd_set *fdset);
宏FD_SET设置文件描述符集fdset中对应于文件描述符fd的位(设置为1),宏FD_CLR清除文件描述符集fdset中对应于文件描述符fd的位(设置为0),宏FD_ZERO清除文件描述符集fdset中的所有位(既把所有位都设置为0)。使用这3个宏在调用select前设置描述符屏蔽位,在调用select后使用FD_ISSET来检测文件描述符集fdset中对应于文件描述符fd的位是否被设置。
过去,描述符集被作为一个整数位屏蔽码得到实现,但是这种实现对于多于32个的文件描述符将无法工作。描述符集现在通常用整数数组中的位域表示,数组元素的每一位对应一个文件描述符。例如,一个整数占32位,那么整数数组的第一个元素代表文件描述符0到31,数组的第二个元素代表文件描述符32到63,以此类推。宏FD_SET设置整数数组中对应于fd文件描述符的位为1,宏FD_CLR设置整数数组中对应于fd文件描述符的位为0,宏FD_ZERO设置整数数组中的所有位都为0。假设执行如下程序后:
#include <sys/select.h>
#include <sys/time.h>
fd_set readset;
FD_ZERO(&readset);
FD_SET(5, &readset);
FD_SET(33, &readset);
则文件描述符集readset中对应于文件描述符6和33的相应位被置为1,如图1所示:
再执行如下程序后:
FD_CLR(5, &readset);
则文件描述符集readset对应于文件描述符6的相应位被置为0,如图2所示:
通常,操作系统通过宏FD_SETSIZE来声明在一个进程中select所能操作的文件描述符的最大数目。例如:
在4.4BSD的头文件中我们可以看到:
#ifndef FD_SETSIZE
#define FD_SETSIZE 1024
#endif
在红帽Linux的头文件<bits/types.h>中我们可以看到:
#define __FD_SETSIZE 1024
以及在头文件<sys/select.h>中我们可以看到:
#include <bits/types.h>
#define FD_SETSIZE __FD_SETSIZE
既定义FD_SETSIZE为1024,一个整数占4个字节,既32位,那么就是用包含32个元素的整数数组来表示文件描述符集。我们可以在头文件中修改这个值来改变select使用的文件描述符集的大小,但是必须重新编译内核才能使修改后的值有效。当前版本的unix操作系统没有限制FD_SETSIZE的最大值,通常只受内存以及系统管理上的限制。
我们明白了文件描述符集的实现机制之后,就可对其进行灵活运用。(以下程序在红帽Linux 6.0下运行通过,函数fd_isempty用于判断文件描述符集是否为空;函数fd_fetch取出文件描述符集中的所有文件描述符)
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/select.h>
struct my_fd_set{
fd_set fs; //定义文件描述符集fs
unsigned int nconnect; //文件描述符集fs中文件描述符的个数
unsigned int nmaxfd; //文件描述符集fs中最大的文件描述符
};
/* 函数fd_isempty用于判断文件描述符集是否为空,为空返回1,不为空则返回0 */
int fd_isempty(struct my_fd_set *pfs)
{
int i;
/* 文件描述符集fd_set是通过整数数组来实现的,所以定义整数数组myset的元素个数为文件描述符集fd_set所占内存空间的字节数除以整数所占内存空间的字节数。
*/
unsigned int myset[sizeof(fd_set) / sizeof(int)];
/* 把文件描述符集pfs->fs 拷贝到数组myset */
memcpy(myset, &pfs->fs, sizeof(fd_set));
for(i = 0; i < sizeof(fd_set) / sizeof(int); i++)
/* 如果myset的某个元素不为0,说明文件描述符集不为空,则函数返回0 */
if (myset[i])
return 0;
return 1; /* 如果myset的所有元素都为0,说明文件描述符集为空,则函数返回1 */
}
/* 函数fd_fetch对文件描述符集进行位操作,把为1的位换算成相应的文件描述符,然后就可对其进行I/O操作 */
void fd_fetch(struct my_fd_set *pfs)
{
struct my_fd_set *tempset; //定义一个临时的结构指针
unsigned int myset[sizeof(fd_set)/sizeof(unsigned int)];
unsigned int i, nbit, nfind, ntemp;
tempset = pfs;
memcpy(myset, &tempset->fs, sizeof(fd_set));
/* 把最大的文件描述符maxfd除以整数所占的位数,得出maxfd在文件描述符集中相应的位对应于整数数组myset的相应元素的下标,目的是为了减少检索的次数 */
nfind = tempset->nmaxfd / (sizeof(int)*8);
for (i = 0; i <= nfind; i++) {
/* 如果数组myset的某个元素为0,说明这个元素所对应的文件描述符集的32位全为0,则继续判断下一元素。*/
if (myset[i] == 0) continue;
/* 如果数组myset的某个元素不为0,说明这个元素所对应的文件描述符集的32位中有为1的,把myset[i]赋值给临时变量ntemp,对ntemp进行位运算,把为1的位换算成相应的文件描述符 */
ntemp = myset[i];
/* nbit记录整数的二进制位数,对ntemp从低到高位进行&1运算,直到整数的最高位,或直到文件描述符集中文件描述符的个数等于0 */
for (nbit = 0; tempset->nconnect && (nbit < sizeof(int)*8); nbit++) {
if (ntemp & 1) {
/* 如果某位为1,则可得到对应的文件描述符为nbit + 32*I,然后我们可对其进行I/O操作。这里我只是做了简单的显示。*/
printf("i = %d, nbit = %d, The file description is %d\n", i, nbit, nbit + 32*i);
/* 取出一个文件描述符后,将文件描述符集中文件描述符的个数减1 */
tempset->nconnect--; }
ntemp >>= 1; // ntemp右移一位
}
}
}
/* 下面的主程序是对以上两个函数的测试 */
main()
{
/* 假设fd1,fd2,fd3为3个文件描述符,实际运用中可为Socket描述符等 */
int fd1 = 7, fd2 = 256, fd3 = 1023, isempty;
struct my_fd_set connect_set;
connect_set.nconnect = 0;
connect_set.nmaxfd = 0;
FD_ZERO(&connect_set.fs);
/* FD_SET操作前对函数fd_isempty进行测试 */
isempty = fd_isempty(&connect_set);
printf("isempty = %d\n", isempty);
FD_SET(fd1, &connect_set.fs);
FD_SET(fd2, &connect_set.fs);
FD_SET(fd3, &connect_set.fs);
connect_set.nconnect = 3;
connect_set.nmaxfd = fd3 ;
/* FD_SET操作后,既把文件描述符加入到文件描述符集之后,对函数fd_isempty进行测试 */
isempty = fd_isempty(&connect_set);
printf("isempty = %d\n", isempty);
/* 对函数fd_ fetch进行测试 */
fd_fetch(&connect_set);
}
/* 程序输出结果为 :*/
isempty is 1
isempty is 0
i = 0, nbit = 7, The file description is 7
i = 8, nbit = 0, The file description is 256
i = 31, nbit = 31, The file description is 1023
playmud
2006-07-20
打赏
举报
回复
select()
Heaven_Redsky
2006-07-20
打赏
举报
回复
void ThreadReceive(PVOID param)
{
static struct sockaddr_in server; // 绑定地址
static SOCKET ListenSocket; // 等待接收数据的socket
char buf[4096];
int len = sizeof(client);
int result;
ListenSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ListenSocket == INVALID_SOCKET)
{
perror("opening stream socket");
exit(0);
}
server.sin_family = PF_INET;
server.sin_addr.s_addr = htonl( INADDR_ANY ); // 任何地址
server.sin_port = htons(LOCAL_PORT);
if (SOCKET_ERROR == bind(ListenSocket, (struct sockaddr *)&server, sizeof(server)) )
{
printf("Error: 绑定失败\n");
exit(1);
closesocket( ListenSocket );
}
printf("socket port %d \n", ntohs(server.sin_port));
while(TRUE)
{
//接收数据
result = recvfrom(ListenSocket, buf, sizeof(buf)-1, 0, (struct sockaddr *)&client, &len);
if ( result > 0 )
{
buf[result] = 0;
inet_ntoa(client.sin_addr), ntohs(client.sin_port));
}
}
closesocket(ListenSocket);
}
HANDLE hReceiveThread;
hReceiveThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadReceive, NULL,0,&dwThreadId);
楼主试试看吧 不行就自己改改
Heaven_Redsky
2006-07-20
打赏
举报
回复
创造一个接收线程就可以了,在线程里边可以While循环接收的
zez
2006-07-20
打赏
举报
回复
死循环一直接收啊.
或者开一个线程一直接收..
都是这样的
xhbpla
2006-07-20
打赏
举报
回复
自己顶
xuanwenchao
2006-07-20
打赏
举报
回复
FD_ZERO(&fdRead);
FD_SET(sockClient,&fdRead);
FD_SET(listenSock,&fdRead);
ret = select(0,&fdRead,NULL,NULL,&t_value);
if(FD_ISSET(sockClient,&fdRead) || FD_ISSET(listenSock,&fdRead))
{
.....................
}
zez
2006-07-20
打赏
举报
回复
自己找点示例代码看看不就知道了..msdn 里就有吧??
当然要 先 select 了,有数据再接收.. 没有数据就阻塞.. cpu肯定就不会100%啦..
死循环一直读,那不死才怪:(
--- select()
这个怎么用法
这个自己搜.........
xhbpla
2006-07-20
打赏
举报
回复
线程里循环接受,cpu也是100%占用,这是怎么回事?
-- -playmud((猪头流氓)(鄙视老迈)(抵制日货))
--- select()
这个怎么用法
android
socket
UDP
通信
本程序实现了android的基于
UDP
的
socket
通信,实现了三次来回通信,即先向服务器发送请求,然后接收服务器回复,再给服务器回复确认,并且可以传递多条数据,每条数据的通信互不冲突。
android发送
UDP
广播demo
压缩包里面有四个项目,分别是android端
UDP
发送、
接受
UDP
广播程序,PC端
UDP
发送、
接受
UDP
广播程序。 大致描述:客户端发送
UDP
广播到局域网,服务端收到广播后,获得客户端ip,发送一次
socket
请求,客户端收到
socket
...
Socket
编程系列之1:Linux-API网络编程入门实战
---------------------------------------------------
Socket
编程系列之1:Linux-API网络编程入门实战 Linux编程环境 Linux文件系统 TCP/IP协议简介 应用层协议简介 TCP网络编程基础 IO复用机制
UDP
网络编程基础 ...
【
Socket
】Linux下
UDP
Socket
的基本流程以及connect、bind函数的使用(C语言实现)
Socket
的原意是“插座”,在计算机通信领域,
socket
被翻译为“套接字”。
Socket
通信主要有两个类型:TCP、
UDP
。...其中,
UDP
Socket
实时
性要求高,可以
接受
一定的数据错误和丢失。例如在线游戏、音视频聊天等场景。
https,
udp
,
socket
区别
创建
socket
连接时,可以指定使用的传输层协议,
socket
可以支持不同的传输层协议(TCP或
UDP
),当使用TCP协议进行连接时,该
socket
连接就是一个TCP连接。
socket
连接一旦建立,通信双方即可开始相互发送数据内容, ...
C语言
69,371
社区成员
243,082
社区内容
发帖
与我相关
我的任务
C语言
C语言相关问题讨论
复制链接
扫一扫
分享
社区描述
C语言相关问题讨论
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章