고정된 메모리에서 버퍼를 잡고 썼다 지웠다 하는데요.
링버퍼를 사용해야 된다고 하는군요..
그런데 정확하게 링버퍼를 왜 사용하는지 잘 모르겟습니다..
고수들의 조언 부탁드려요..
링버퍼의 장점은 순환할수 있다지요.
링버퍼의 구현은 선형의 버퍼이지만 논리적으로 시작과 끝이 만나 있어서 계속 순환하면서 버퍼를 쓸수 있습니다.
네트워크 송수신 버퍼로 사용하기에 좋습니다.
울랄라~ 호기심 천국~!!http://www.ezdoum.com
아래는 링버퍼를 사용한 예입니다. ClientDataHandler 가 집어 넣는 넘이고 MakePacket가 꺼내 쓰는 넘이지요..
typedef struct _FD_QUEUE{ /* FD QUEUE(원형) */ unsigned char Queue[BUFF_LEN];/* fd data buffer */ int fd; /* fd 번호 */ int sttime; /* conn time */ int Pos; /* 큐의 끝 */ int PkCurr; /* 큐의 시작 */ int cnt; /* fd패킷 만든 횟수 */ }FD_QUEUE; /******************************************************************************* * 설명 : 큐에 있는 것으로 패킷을 만든다. * Prototype : MakePacket(fd) * Arguments : * Return : ******************************************************************************/ int MakePacket(fd) int fd; { register unsigned char *src; char packet[PACKET_LEN]; char ptmp[5]; FD_PACKET *fdp; int plen = 0, plen2 = 0; int rtn = 0, dif = 0; memset(packet, 0x00, sizeof(packet)); memset(ptmp, 0x00, sizeof(ptmp)); while(1){ src = (unsigned char *)(fdq[fd]->Queue + fdq[fd]->PkCurr); /* 패킷 만들어야 할 사이즈는 얼마? */ if((fdq[fd]->PkCurr + PACKET_SIZE) >= BUFF_LEN){ dif = BUFF_LEN - fdq[fd]->PkCurr; memcpy(ptmp, src, dif); memcpy(ptmp + dif, fdq[fd]->Queue, PACKET_SIZE - dif); }else{ memcpy(ptmp, src, PACKET_SIZE); } plen = atoi(ptmp) + 4; /* 패킷이 크면,, 한방에 안만들어 진다. 버퍼에 원하는 사이즈 만큼 들어 왔는지 확인해보자.. */ plen2 = (fdq[fd]->Pos < fdq[fd]->PkCurr) ? BUFF_LEN + fdq[fd]->Pos : fdq[fd]->Pos; plen2 = plen2 - fdq[fd]->PkCurr; if(plen2 < plen) { OUT("[%s] : [Msg] fd[%02d] MakePacket SAVE ptmp[%4s] plen[%d] plen2[%d]\n", pname, fd, ptmp ,plen, plen2); return 1; } /* 패킷을 맹글어 볼까나 */ OUT("[%s] : [Msg] fd[%02d] MakePacket START ptmp[%4s] plen[%d] plen2[%d]\n", pname, fd, ptmp ,plen, plen2); if((fdq[fd]->PkCurr + plen) >= BUFF_LEN){ dif = BUFF_LEN - fdq[fd]->PkCurr; memcpy(packet, src, dif); memcpy(packet + dif, fdq[fd]->Queue, plen - dif); fdq[fd]->PkCurr = plen - dif; }else{ memcpy(packet, src, plen); fdq[fd]->PkCurr += plen; } OUT("[%s] : [Msg] fd[%02d] MakePacket >> END!! plen[%d] dif[%d]\n", pname, fd, plen, dif); /* 만들어진 패킷을 safe 쓰레드 변수로 옮긴다. * malloc은 WorkerThread에서 free */ fdp = calloc(1, sizeof(FD_PACKET)); memcpy(fdp->Packet, packet, plen); fdp->fd = fd; fdp->len = plen; fdp->sttime = fdq[fd]->sttime; /* tpool job큐에 등록 */ rtn = tpool_add_work(zt_pool, WorkerThread, fdp); OUT("[%s] : [Msg] fd[%02d] MakePacket Thread pool add rtn[%d]\n", pname, fd, rtn); if(fdq[fd]->PkCurr >= fdq[fd]->Pos) break; /* 큐에 들어온거 다 살펴 봤당.. 그만 루프 빠지자 */ } return 1; } /***************************************************************************** * 설명 : Client 의 Data를 처리하는 Handler * Prototype : int ClientDataHandler(event, fd, type) * Arguments : * Return : ****************************************************************************/ int ClientDataHandler(event, fd ,type) EVENT *event; int fd, type; { int rtn; int dif = 0; int errcnt = 0; char buff[4096]; start: memset(buff, 0x00, sizeof(buff)); rtn = read(fd, buff, sizeof(buff)); /**** OUT("[%s] : [Msg] ClientDataHandler READ fd[%02d] buff[%s] rtn[%d]\n", pname, fd, buff, rtn); ****/ fdq[fd]->cnt++; if(rtn <= 0){ /* 컨넥션 끝났거나, 에러 받았다... */ if(errno == EINTR && errcnt < 3) { /* 인터럽트(시그널)에 의한 에러는 봐준다.. * (어쩌다 함씩 생긴당.. 주의) */ errcnt ++; OUT("[%s] : [Err] fd[%02d] ClientDataHandler TRcnt[%d] errno[EINTR] errcnt[%d]\n", pname, fd, fdq[fd]->cnt, errcnt); usleep(1000); goto start; }else{ /* 컨넥션 정리 작업을 한다. * 1) 동적할당 소켓큐 해제, * 2) 소켓 close */ OUT("[%s] : [Err] fd[%02d] ClientDataHandler Connect Close TRcnt[%d] errno[%d][%s]\n", pname, fd, fdq[fd]->cnt, errno, strerror(errno)); free(fdq[fd]); fdq[fd] = NULL; close(fd); AppDelEvent(event, type); } return 1; } /* OUT("[%s] : [Msg] ClientDataHandler READ fd[%02d] buff[%s] rtn[%d]\n", pname, fd, buff, rtn); OUT("[%s] : [Msg] ClientDataHandler READ fd[%02d] rtn[%d] Cur[%d] Pos[%d] cnt[%d]\n", pname, fd, rtn, fdq[fd]->PkCurr, fdq[fd]->Pos, fdq[fd]->cnt); */ if((fdq[fd]->Pos + rtn) >= BUFF_LEN){ dif = BUFF_LEN - fdq[fd]->Pos; memcpy(fdq[fd]->Queue + fdq[fd]->Pos, buff, dif); memcpy(fdq[fd]->Queue, buff + dif, rtn - dif); fdq[fd]->Pos = rtn - dif; }else{ memcpy(fdq[fd]->Queue + fdq[fd]->Pos , buff, rtn); fdq[fd]->Pos += rtn; } OUT("[%s] : [Msg] fd[%02d] ClientDataHandler READ rtn[%d] Cur[%d] Pos[%d] cnt[%d]\n", pname, fd, rtn, fdq[fd]->PkCurr, fdq[fd]->Pos, fdq[fd]->cnt); MakePacket(fd); return 1; }
텍스트 포맷에 대한 자세한 정보
<code>
<blockcode>
<apache>
<applescript>
<autoconf>
<awk>
<bash>
<c>
<cpp>
<css>
<diff>
<drupal5>
<drupal6>
<gdb>
<html>
<html5>
<java>
<javascript>
<ldif>
<lua>
<make>
<mysql>
<perl>
<perl6>
<php>
<pgsql>
<proftpd>
<python>
<reg>
<spec>
<ruby>
<foo>
[foo]
링버퍼
링버퍼의 장점은 순환할수 있다지요.
링버퍼의 구현은 선형의 버퍼이지만
논리적으로 시작과 끝이 만나 있어서 계속
순환하면서 버퍼를 쓸수 있습니다.
네트워크 송수신 버퍼로 사용하기에 좋습니다.
울랄라~ 호기심 천국~!!
http://www.ezdoum.com
예제
아래는 링버퍼를 사용한 예입니다.
ClientDataHandler 가 집어 넣는 넘이고
MakePacket가 꺼내 쓰는 넘이지요..
울랄라~ 호기심 천국~!!
http://www.ezdoum.com
댓글 달기