关于select函数的各个参数以及多路I/O复用,上面的这篇博客介绍的很清楚了.走一遍实现代码
这个代码主要是实现udp同时能够进行收发
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc,char *argv[])
{
int udpfd = 0;
struct sockaddr_in saddr;
struct sockaddr_in caddr;
//初始化结构体地址
bzero(&saddr,sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8000);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
bzero(&caddr,sizeof(caddr));
caddr.sin_family = AF_INET;
caddr.sin_port = htons(8000);
//创建套接字
if( (udpfd = socket(AF_INET,SOCK_DGRAM, 0)) < 0)
{
perror("socket error");
exit(-1);
}
//套接字端口绑字
if(bind(udpfd, (struct sockaddr*)&saddr, sizeof(saddr)) != 0)
{
perror("bind error");
close(udpfd);
exit(-1);
}
printf("input: \"sayto 192.168.220.X\" to sendmsg to somebody\033[32m\n");
while(1)
{
/*
typedef struct
{
#ifdef__USE_XOPEN
__fd_maskfds_bits[__FD_SETSIZE/__NFDBITS];
#define__FDS_BITS(set)((set)->fds_bits)
#else
__fd_mask__fds_bits[__FD_SETSIZE/__NFDBITS];
#define__FDS_BITS(set)((set)->__fds_bits)
#endif
}fd_set
select()机制中提供一fd_set的数据结构,实际上是一long类型的数组,
*/
char buf[100]="";
fd_set rset; //创建文件描述符的聚合变量
FD_ZERO(&rset); //文件描述符聚合变量清0
FD_SET(0, &rset);//将标准输入添加到文件描述符聚合变量中
FD_SET(udpfd, &rset);//将udpfd添加到文件描述符聚合变量中
write(1,"UdpQQ:",6);//向标准输出中写入:UdpQQ字样
if(select(udpfd + 1, &rset, NULL, NULL, NULL) > 0)//select第一个参数是最大文件文描述符的数量+1
{
if(FD_ISSET(0, &rset))//测试0是否可读写
{
fgets(buf, sizeof(buf), stdin);//从键盘输入字符存入缓冲区
buf[strlen(buf) - 1] = '\0';//缓冲字符串末尾加入'\0'
if(strncmp(buf, "sayto", 5) == 0)//比较buf中有没有sayto 字样
{
char ipbuf[16] = "";
inet_pton(AF_INET, buf+6, &caddr.sin_addr);//给addr套接字地址再赋值. 如果buff后面接地址了 那么将那个地址转换
printf("\rsay to %s\n",inet_ntop(AF_INET,&caddr.sin_addr,ipbuf,sizeof(ipbuf)));
continue;
}
else if(strcmp(buf, "exit")==0)//如果出现exit 则退出
{
close(udpfd);
exit(0);
}
sendto(udpfd, buf, strlen(buf),0,(struct sockaddr*)&caddr, sizeof(caddr));//发送出去
}
if(FD_ISSET(udpfd, &rset))//测试udpfd是否可读写
{
struct sockaddr_in addr;
char ipbuf[INET_ADDRSTRLEN] = "";
socklen_t addrlen = sizeof(addr);
bzero(&addr,sizeof(addr));
//显示收到信息
recvfrom(udpfd, buf, 100, 0, (struct sockaddr*)&addr, &addrlen);
printf("\r\033[31m[%s]:\033[32m%s\n",inet_ntop(AF_INET,&addr.sin_addr,ipbuf,sizeof(ipbuf)),buf);
}
}
}
return 0;
}
测试过程有点绕 首先我们执行可执行文件 我们可以发现
input: "sayto 192.168.220.X" to sendmsg to somebody
UdpQQ:nihao
[127.0.0.1]:nihao
写出去写信息 然后本机提示收到了
下面在键盘中输入
UdpQQ:sayto 202.199.xxx.xxx //你的电脑的ip地址
UdpQQ:zaijian//在输入你想说的话
[202.199.xxx.xxx]:zaijian//就会直接在屏幕上显示收到了什么信息
至此就可以完成同时收发.