- 论坛徽章:
- 15
|
本帖最后由 yulihua49 于 2017-02-08 20:29 编辑
cat AIO_tcp.c - [/font][/align][align=left][font=Menlo]/**********************************************[/font][/align][align=left][font=Menlo] * @(#) SDBC 7.1 TCP RECV/SEND Tools *[/font][/align][align=left][font=Menlo] * to suport coroutine[/font][/align][align=left][font=Menlo] **********************************************/[/font][/align][align=left][font=Menlo]#include <sys/socket.h>[/font][/align][align=left][font=Menlo]#include <sys/time.h>[/font][/align][align=left][font=Menlo]#include <unistd.h>[/font][/align][align=left][font=Menlo]#include <fcntl.h>[/font][/align][align=left][font=Menlo]#include <sc.h>[/font][/align]
- [align=left][font=Menlo]#ifndef MIN[/font][/align][align=left][font=Menlo]#define MIN(a,b) ((a)<(b))?(a):(b)[/font][/align][align=left][font=Menlo]#endif[/font][/align]
- [align=left][font=Menlo]static T_YIELD yield=NULL;[/font][/align]
- [align=left][font=Menlo]T_YIELD get_yield()[/font][/align][align=left][font=Menlo]{[/font][/align][align=left][font=Menlo] return yield;[/font][/align][align=left][font=Menlo]}[/font][/align]
- [align=left][font=Menlo]T_YIELD set_yield(T_YIELD new_yield)[/font][/align][align=left][font=Menlo]{[/font][/align][align=left][font=Menlo]T_YIELD oldyield=yield;[/font][/align][align=left][font=Menlo] yield=new_yield;[/font][/align][align=left][font=Menlo] return oldyield;[/font][/align][align=left][font=Menlo]}[/font][/align]
- [align=left][font=Menlo]//timeout for second [/font][/align][align=left][font=Menlo]int RecvNet(int socket,char *buf,int n,int timeout)[/font][/align][align=left][font=Menlo]{[/font][/align][align=left][font=Menlo]int bcount=0,br,ret;[/font][/align][align=left][font=Menlo]int i,repeat=0;[/font][/align][align=left][font=Menlo]int fflag=-1;[/font][/align]
- [align=left][font=Menlo] if(socket<0) return SYSERR;[/font][/align][align=left][font=Menlo] if(!buf && n<0) return 0;[/font][/align][align=left][font=Menlo] if(yield) {[/font][/align][align=left][font=Menlo] fflag=fcntl(socket,F_GETFL,0);[/font][/align][align=left][font=Menlo] if(fflag!=-1) fcntl(socket,F_SETFL,fflag|O_ASYNC|O_NONBLOCK); //异步操作[/font][/align][align=left][font=Menlo] } else if(timeout>0) {[/font][/align][align=left][font=Menlo] struct timeval tmout;[/font][/align][align=left][font=Menlo] tmout.tv_sec=timeout;[/font][/align][align=left][font=Menlo] tmout.tv_usec=0;[/font][/align][align=left][font=Menlo] ret=setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&tmout,sizeof(tmout));[/font][/align][align=left][font=Menlo] if(ret) ShowLog(1,"%s:setsockopt errno=%d,%s",__FUNCTION__,errno,strerror(errno));[/font][/align][align=left][font=Menlo] }[/font][/align]
- [align=left][font=Menlo] *buf=0;[/font][/align][align=left][font=Menlo] br=0;[/font][/align]
- [align=left][font=Menlo] while(bcount<n){[/font][/align][align=left][font=Menlo] if((br=read(socket,buf,n-bcount))>0){[/font][/align][align=left][font=Menlo] bcount+=br;[/font][/align][align=left][font=Menlo] buf+=br;[/font][/align][align=left][font=Menlo] repeat=0;[/font][/align][align=left][font=Menlo] continue;[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] if(fflag==-1 && errno==EAGAIN) return TIMEOUTERR;[/font][/align][align=left][font=Menlo] if(br<=0 && errno && errno != EAGAIN){[/font][/align][align=left][font=Menlo] if(errno!=ECONNRESET)[/font][/align][align=left][font=Menlo] ShowLog(1,"%s:br=%d,err=%d,%s",__FUNCTION__,br,errno,strerror(errno));[/font][/align][align=left][font=Menlo] break;[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] if(bcount < n && fflag!=-1) { //切换任务[/font][/align][align=left][font=Menlo] if(repeat++>3) return -errno;[/font][/align][align=left][font=Menlo]/*[/font][/align][align=left][font=Menlo]yield:[/font][/align][align=left][font=Menlo]1.找到当前线程的context。找不到返回-1;(后续任务以同步阻塞完成)[/font][/align][align=left][font=Menlo]2.把事件提交给epoll,作为resume的条件。[/font][/align][align=left][font=Menlo]3.swapcontext,挂起这个任务,线程回到epoll_wait,可以为别人服务了。[/font][/align][align=left][font=Menlo]4.一旦这个任务的事件发生了,立即由epoll_wait激活一个线程,抓取相应的context,使用setcontext,恢复任务现场,返回0.[/font][/align][align=left][font=Menlo]后续的动作就是继续NONBLOCK的IO。直至完成返回。[/font][/align][align=left][font=Menlo]*/[/font][/align][align=left][font=Menlo]ShowLog(5,"%s:tid=%lx,socket=%d,yield to schedle bcount=%d/%d",__FUNCTION__,pthread_self(),socket,bcount,n);[/font][/align][align=left][font=Menlo] i=yield(socket,0,timeout);[/font][/align][align=left][font=Menlo] if(i<0) {[/font][/align][align=left][font=Menlo] if(timeout>0) {[/font][/align][align=left][font=Menlo] struct timeval tmout;[/font][/align][align=left][font=Menlo] tmout.tv_sec=timeout;[/font][/align][align=left][font=Menlo] tmout.tv_usec=0;[/font][/align][align=left][font=Menlo] ret=setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&tmout,sizeof(tmout));[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] fcntl(socket,F_SETFL,fflag);[/font][/align][align=left][font=Menlo] fflag=-1;[/font][/align][align=left][font=Menlo] if(i==TIMEOUTERR) return i;[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] if(fflag!=-1) fcntl(socket,F_SETFL,fflag);[/font][/align][align=left][font=Menlo] return bcount==0?-1:bcount;[/font][/align][align=left][font=Menlo]}[/font][/align]
- [align=left][font=Menlo]int SendNet(int socket,char *buf,int n,int MTU)[/font][/align][align=left][font=Menlo]{[/font][/align][align=left][font=Menlo]int bcount,bw;[/font][/align][align=left][font=Menlo]int sz,i=0;[/font][/align][align=left][font=Menlo]int fflag=-1;[/font][/align][align=left][font=Menlo]size_t SendSize;[/font][/align]
- [align=left][font=Menlo] if(socket<0) return SYSERR;[/font][/align][align=left][font=Menlo] if(yield) {[/font][/align][align=left][font=Menlo] fflag=fcntl(socket,F_GETFL,0);[/font][/align][align=left][font=Menlo] if(fflag != -1) fcntl(socket,F_SETFL,fflag|O_NONBLOCK); //异步操作[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] bcount=0;[/font][/align][align=left][font=Menlo] bw=0;[/font][/align][align=left][font=Menlo] if(MTU>500) SendSize=MTU;[/font][/align][align=left][font=Menlo] else SendSize=n;[/font][/align][align=left][font=Menlo] while(bcount<n){[/font][/align][align=left][font=Menlo] sz=MIN(n-bcount,SendSize);[/font][/align][align=left][font=Menlo] if((bw=write(socket,buf,sz))>0){[/font][/align][align=left][font=Menlo] bcount+=bw;[/font][/align][align=left][font=Menlo] buf+=bw;[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] if(bw<0&&errno!=EAGAIN) {[/font][/align][align=left][font=Menlo] ShowLog(1,"%s:err=%d,%s",__FUNCTION__,errno,strerror(errno));[/font][/align][align=left][font=Menlo] break;[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] if(bw < sz && fflag != -1) { //切换任务[/font][/align][align=left][font=Menlo]//ShowLog(5,"%s:tid=%lx,socket=%d,yield bw=%d/%d",__FUNCTION__,pthread_self(),socket,bw,sz);[/font][/align][align=left][font=Menlo] i=yield(socket,1,0); [/font][/align][align=left][font=Menlo] if(i<0) {[/font][/align][align=left][font=Menlo] fcntl(socket,F_SETFL,fflag);[/font][/align][align=left][font=Menlo] fflag = -1;[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] }[/font][/align][align=left][font=Menlo] if(fflag != -1) fcntl(socket,F_SETFL,fflag);[/font][/align][align=left][font=Menlo] return bcount==0?-1:bcount;[/font][/align][align=left][font=Menlo]}[/font][/align]
复制代码 |
|