|
질문을 자세히 읽어보지 않았습니다.
어쨌든 몇 줄 읽어본 바로는, Accept가 항상 일어나야 한다고 생각하시는 것 같은데요.
소켓의 통신 구조는 전화기를 사용하는 방식과 유사합니다.
아래의 간략한 요약에서 감을 잡으시기 바랍니다.
Open / Close 전화선을 전화소켓에 꽂거나 뽑습니다.
Bind 우리가 사용하는 전화기는 다목적이기 때문에 내선(포트) 설정을 합니다.
Listen 전화를 받는쪽이 전화오는 소리를 들을 수 있는 위치에 있게 합니다.
Connect 전화번호(IP Address)를 이용해 목적지에 전화를 겁니다.
Accept 전화 벨은 울리는데 받을지 말지 결정합니다.
Read / Write 송수화기를 통해 말을 하거나 듣습니다.
Disconnect 전화를 끊습니다.
대충 이런식입니다.
즉, Accept는 클라이언트로 부터의 접속을 허용할지 말지에 대해 딱 한 번 결정내리는 용도로 사용하지,
송수신시 매번 행해지는것이 아닙니다.
이영섭 님이 쓰신 글 :
: 볼랜드로 서버/클라이언트를 만들어보려고 하는데 잘 안되서 문의드려요
:
: 클라이언트에서 소켓 연결할때는 accept에서 반응을 하는데, 패킷을 만들어서 보내니까 accept에서 반응을 안하더라구요.
: 아래 부분은 서버 쪽 소스인데, MFC로 구현된걸 찾으면서 C빌더로 바꾸다보니 마음대로 안되네요;;;
:
: 질문을 정리하면
: - 소켓 연결할 때는 accept에 반응이 있는데, 패킷을 보낼때는 왜 반응이 없는지 알고싶습니다.
:
: -----
: void TForm1::Main()
: {
: int clen;
: cmdMessage *rcvState, *sendMsg;
:
: byte *rcvbuf;
:
: SOCKADDR_IN client_addr;
:
: while(1)
: {
: if(!SocketListenTCP(ssock))
: {
: ShowMessage("실패");
: return;
: }
: csock = accept(ssock, (SOCKADDR*)&client_addr, &clen); // 반응있음
: // Receive
: int nRecvPacketSize = sizeof(cmdMessage);
: rcvbuf = (Byte*)malloc(nRecvPacketSize);
: memset(rcvbuf, 0x00,nRecvPacketSize);
:
: if(listen(ssock, 5) == SOCKET_ERROR)
: {
: ShowMessage("ERROR");
: }
:
: // read(csock, (char*)rcvbuf, nRecvPacketSize);
: int nRecvCount = ReceiveTCPData(csock, (char*)rcvbuf,
: nRecvPacketSize, 10);
:
: int length = strlen(rcvbuf);
: if(length <= 0)
: {
: Sleep(1);
: continue;
: }
: // Send
: rcvState = (cmdMessage*)rcvbuf;
: Parsing(rcvState); // 메시지를 만들어서 클라이언트에 던지는 함수
: return;
: }
: }
:
: //-----------------------------------------------------------------
:
: int ReceiveTCPData(SOCKET s, char * lpBuffer, int nSizeToRead, int nTimeout)
: {
: register int i;
: register int nread = 0;
: register int rtn;
: int elapsed = 0;
: int nErrorResult = 0;
: char szMessage[100] = "0x00,";
: bool flag;
: u_long FAR arg; /* blocking, non-blocking 변환용 */
: int nReturn;
: unsigned long time_start, time_elps; // time out 시간보정
:
: if(nTimeout >= 0)
: {
: arg = 1;
: ioctlsocket(s, FIONBIO, &arg); /* non-blocking mode */
: }
: else
: {
: arg = 0;
: nReturn = ioctlsocket(s, FIONBIO, &arg); /* blocking mode */
: }
:
: for(i = 0; i < nSizeToRead; )
: {
: time_start = GetTickCount();
:
: rtn = recv(s, lpBuffer + i, nSizeToRead - nread, 0);
: if (rtn == 0) /* EOF */ //-- Disconnect Occurs
: {
: if( flag == true ) return nread;
: arg = 0; ioctlsocket(s, FIONBIO, &arg); //* blocking mode */
: return SOCKET_DISCONNECTED;
: }
: else if (rtn < 0) // error
: {
:
: //if( flag == true ) return nread;
: nErrorResult = GetLastSocketErrorMessage(szMessage);
: if(nErrorResult == WSAECONNABORTED)
: {
: return SOCKET_CLOSED;
: }
: else if(nErrorResult == WSAECONNRESET)
: {
: return SOCKET_DISCONNECTED;
: }
: else if (nTimeout >= 0)
: {
: if (elapsed >= nTimeout) // Occur Timeout
: { //* time out
: arg = 0; ioctlsocket(s, FIONBIO, &arg); // blocking mode
: if( flag == true ) return nread;
: return SOCKET_READTIMEOUT;
: }
: Sleep(1);
:
: time_elps = GetTickCount() - time_start;
: elapsed += time_elps;
: }
: else // Socket Disconnected // Socket Closed
: {
: if( flag == true ) return nread;
: return SOCKET_CLOSED;
: }
: }
: else //* rtn(bytes)를 read한 경우 */
: {
: if( i == 0 ) flag = true;
: nread += rtn;
: i += rtn;
: }
: }
:
: arg = 0;
: ioctlsocket(s, FIONBIO, &arg); /* blocking mode */
:
: return nread;
: }
|