sokcet常用编程函数

89 篇文章 0 订阅

1.设置发送超时和接收超时。

select模型
一般需要同时处理多个文件描述符,即多个socket时,考虑select模型。

Select的函数格式(我所说的是Unix系统下的伯克利socket编程,和windows下的有区别,一会儿说明):
int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);
参数一:最大的文件描述符加1。
参数二:用于检查可读性,
参数三:用于检查可写性,
参数四:用于检查带外数据,
参数五:一个指向timeval结构的指针,用于决定select等待I/o的最长时间。如果为空将一直等待。timeval结构的定义:struct timeval{
long tv_sec; // seconds
long tv_usec; // microseconds
}
返回值
>0:就绪描述字的正数目
-1:出错
0 :超时
readset writeset exceptset指定我们要让内核测试读、写和异常条件的描述字。如果对某一个的条件不感兴趣,就可以把它设为NULL。如果三个指针都为NULL,我们就有了一个比sleep()函数更为精确的定时器(sleep()以毫秒为最小单位,这个以微秒为单位)。
select使用描述字集,典型地是一个整数数组,其中每个整数中的每一位对应一个描述字。假设使用32位整数,那么该数组的第一个元素对应于描述字0~31,第二个元素对应于描述字32~63,依此类推。所有的实现细节都与应用程序无关,它们隐藏在名为fd_set的数据类型和以下四个宏中:
void FD_ZERO (fd_set *fdset); // clear all bits in fdset
void FD_SET (int fd,fd_set *fdset); // turn on the bit for fd in fdset
void FD_CLR (int fd,fd_set *fdset); // turn off the bit for fd in fdset
intFD_ISSET(int fd,fd_set *fdset); // is the bit for fd on in fdset
eg:
定义一个fd_set变量,然后打开描述字1.4.5对应的位:
fd_set fdset;
FD_ZERO (&fdset); // 如果不初始化,会导致不可预期的后果
FD_SET (1,&fdset);
FD_SET (4,&fdset);
FD_SET (5,&fdset);
int maxfdp1参数指定待测试的描述字个数,它的值是待测试的最大描述字加1。
举例:

main()
{
int sock; int fd;
fd_set fds;
struct timeval timeout={3,0}; //select等待3微秒,3微秒轮询,要非阻塞就置0
char buffer[256]={0}; //256字节的接收缓冲区
/* 假定已经建立UDP连接,具体过程不写,简单,当然TCP也同理,主机ip和port都已经给定,要写的文件已经打开
sock=socket(...);
bind(...);
fd=open(...); */
while⑴
{
FD_ZERO(&fds); //每次循环都要清空集合,否则不能检测描述符变化
FD_SET(sock,&fds); //添加描述符
FD_SET(fd,&fds); //同上
timeout.tv_sec=3;
timeout.tv_usec=0;//select函数会不断修改timeout的值,所以每次循环都应该重新赋值[windows不受此影响]
maxfdp=sock>fd?sock+1:fd+1; //描述符最大值加1
switch(select(maxfdp,&fds,&fds,NULL,&timeout)) //select使用
{
case -1: exit(-1);break; //select错误,退出程序
case 0:break; //再次轮询
default:
if(FD_ISSET(sock,&fds)) //测试sock是否可读,即是否网络上有数据
{
recvfrom(sock,buffer,256,.....);//接受网络数据
if(FD_ISSET(fd,&fds)) //测试文件是否可写
write(fd,buffer...);//写入文件
buffer清空;
}// end if break;
}// end switch
}//end while
}//end main
其它模型
Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect、accept、recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回)。
可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高)方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。

如果用socket的recvfrom或者sendto,默认是没有超时机制的,即阻塞模式。如果要设置超时,则通过以下方法:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <time.h>


struct timeval timeout;
timeout.tv_sec = 3;//3秒
timeout.tv_usec = 0;//0微秒 
 //设置发送超时
setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO, (char *)&timeout,sizeof(struct timeval));
//设置接收超时
setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO, (char *)&timeout,sizeof(struct timeval))


2.获取错误码和错误原因
#include <errno.h>
printf("err no = %d, err msg = %s\r\n",errno,strerror(errno));


3.mac 地址 字符串-》数组
 char mac[] = "FF-B3-3C-67-A4-05";
    short m[6];
    sscanf(mac, "%x-%x-%x-%x-%x-%x",(int *)&m[0],(int *)&m[1],(int *)&m[2],(int *)&m[3], (int *)&m[4], (int *)&m[5]);


4.起线程
全局变量:pthread_t debug_thread;
线程主函数:
void * debug_thread_func(void* args)
{
while(1)
{
printf("hello thread !");
}
return ((void *)0);
}
主进程中
int main()
{
pthread_create(&debug_thread,NULL,debug_thread_func,NULL);
}


5.定时器
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
typedef void (*timerFuncPtr)(int);
void init_sig_action ( timerFuncPtr funcPtr , int x )
{
struct sigaction tact;
        tact.sa_handler = (*funcPtr) ;
       tact.sa_flags = 0;
      sigemptyset (&tact.sa_mask);
     sigaction( SIGALRM, &tact, NULL );
}
void init_time( unsigned int tv_sec, unsigned int tv_usec)
{
struct itimerval value;
    
       value.it_value.tv_sec = tv_sec;
     
      value.it_value.tv_usec= tv_usec;


      value.it_interval = value.it_value;


   setitimer(ITIMER_REAL,&value,NULL);


}

void dhcp_timer_func( int signo)
{
}
int main()

init_sig_action (&dhcp_timer_func,0);
init_time(2,0);





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值