ݺߣ

ݺߣShare a Scribd company logo
TCP Echo Server & Client
Basic example
Source
https://www.dropbox.com/s/t1t4kqvauypf121/TCPEcho.zip
TCP Echo Client
1. Socket()을 이용하여 TCP Socket생성
2. connect()를 이용하여 서버와의 연결을 설정
3. send(), recv()를 이용하여 통신을 수행
4. close를 이용하여 통신 종료
SOCKET 생성
WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
(sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
winsock의 경우 사용 전에 초기화를 해주어야 함(유닉스에서는 없는 부분)
MAKEWORD(2,0)은 winsock 2.0을 쓰겠다는 뜻.
IPPROTO_TCP라는 스트림 기반(SOCK_STREAM) 프로토콜을 이용하여
IPv4(PF_INET)에서 작동하도록 만들어진 소켓이라는 뜻.
socket이라고 다 같은게 아니고 어떤 프로토콜을 사용할지 미리 설정하는 듯
TCP Echo Client
1. Socket()을 이용하여 TCP Socket생성
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740506(v=vs.85).aspx
SERVER 주소 구조체 생성
struct sockaddr_in echoServAddr;
memset(&echoServAddr, 0, sizeof(echoServAddr));
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = inet_addr(servIP);
echoServAddr.sin_port = htons(echoServPort);
주소 패밀리를 IPv4(AF_INET)로 지정하고, ip와 port번호를 설정
( 유닉스에서는 inet_addr 대신 inet_pton 사용)
inet_addr로 문자열을 binary로 변환
htons로 port번호도 변환한다.
TCP Echo Client
1. Socket()을 이용하여 TCP Socket생성
연결 설정
connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr))
만들어둔 socket과 socket구조체를 이용하여 연결을 설정
sockaddr_in 구조체가 IPv4를 위한 형식이고
connect에서는 범용적으로 사용할 수 있는 구조체인 sockaddr로 형변환 하여 사용한다.
TCP Echo Client
2. connect()를 이용하여 서버와의 연결을 설정
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740496(v=vs.85).aspx
echo문자열을 서버로 전송
echoStringLen = strlen(echoString);
send(sock, echoString, echoStringLen, 0)
argv로 넘겨준 echoString과 echoStringLen을 이용하여 echo 문자열을 전송한다.
send는 전송한 byte수를 return하며 echoStringLen과 비교하여
제대로 전송되었는지를 확인한다.
TCP Echo Client
3. send(), recv()를 이용하여 통신을 수행
echo 서버의 응답 수신
totalBytesRcvd = 0;
printf("Received: ");
while (totalBytesRcvd < echoStringLen)
{
if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
DieWithError("recv() failed or connection closed prematurely");
totalBytesRcvd += bytesRcvd;
echoBuffer[bytesRcvd] = '0';
printf("%s", echoBuffer);
}
서버에서 보낸 메세지가 recv()가 받을 수 있는 크기보다 클 경우가 있으므로 while문을 돌면서
반복해서 데이터를 수신한다.
recv()는 수신할 데이터가 있을 때까지 멈춰있는 block함수라 함
TCP Echo Client
3. send(), recv()를 이용하여 통신을 수행
연결 종료
closesocket(sock);
WSACleanup(); /* Cleanup Winsock */
socket을 close한다.
winsock의 경우 WSACleanup()으로 윈도우 소켓도 닫는다.
TCP Echo Client
4. close를 이용하여 통신 종료
TCP Echo Server
1. Socket()을 이용하여 TCP Socket생성
2. bind()를 통해 소켓에 포트 번호를 할당
3. listen()을 통해 해당 포트가 연결을 받아들이도록 시스템에 알림
4. 다음과 같은 일을 계속적으로 반복
1. accept()를 통해 각 클라이언트와 통신에 필요한 새로운 소켓을 획득
2. 새롭게 생성된 클라이언트 소켓에 send() recv()를 호출하여 통신을 수행
3. close()를 통해 클라이언트와 연결 종료
SOCKET 생성
WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
(sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
winsock의 경우 사용 전에 초기화를 해주어야 함(유닉스에서는 없는 부분)
MAKEWORD(2,0)은 winsock 2.0을 쓰겠다는 뜻.
IPPROTO_TCP라는 스트림 기반(SOCK_STREAM) 프로토콜을 이용하여
IPv4(PF_INET)에서 작동하도록 만들어진 소켓이라는 뜻.
socket이라고 다 같은게 아니고 어떤 프로토콜을 사용할지 미리 설정하는 듯
TCP Echo Server
1. Socket()을 이용하여 TCP Socket생성 ( client와 동일함 )
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740506(v=vs.85).aspx
SERVER 주소 구조체 생성
struct sockaddr_in echoServAddr;
memset(&echoServAddr, 0, sizeof(echoServAddr));
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
echoServAddr.sin_port = htons(echoServPort);
IPv4를 사용
htons로 port번호 변환
와일드 카드 주소(INADDR_ANY)로 설정.
시스템에는 하나 이상의 IP주소가 있을 수 있는데 와일드 카드 주소로 설정하면
사용할 IP주소를 알아서 찾아준다고 하는 것 같음.
찾아보니 서버로 연결된 어떤 IP로 들어오든 (포트만 맞다면) 연결해준다는 얘기
TCP Echo Server
1. Socket()을 이용하여 TCP Socket생성
http://zerobell.tistory.com/5
SOCKET을 지정한 IP주소 및 포트에 바인딩
bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr))
client는 connect()하기 위해 서버의 주소가 있어야 하고
server는 bind()하기 위해 자신의 주소가 필요함
위에서 지정한 주소 구조체(자신의 IP주소와 port에 대한 정보가 담긴)를 이용하여
socket과 bind()함
TCP Echo Server
2. bind()를 통해 소켓에 포트 번호를 할당
http://msdn.microsoft.com/en-us/library/windows/desktop/ms737550(v=vs.85).aspx
SOCKET을 연결에 대한 대기상태로 전환
listen(servSock, MAXPENDING)
listen()을 해주어야 연결 요청을 받을 수 있음
listen() 상태가 아닌 서버로의 (client의) connect()호출은 실패하게 된다.
TCP Echo Server
3. listen()을 통해 해당 포트가 연결을 받아들이도록 시스템에 알림
accept()를 통해 각 클라이언트와 통신에 필요한 새로운 소켓을 획득
clntLen = sizeof(echoClntAddr);
clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, &clntLen
printf("Handling client %sn", inet_ntoa(echoClntAddr.sin_addr));
listen() 상태에서 client의 접속이 감지되면 server에서는 아까 만들어둔 소켓으로 직접 통신을 하는 것
이 아니라, accept()를 이용하여 다른 소켓을 생성한다.
accept()는 새로운 소켓의 식별자를 반환한다. (새로 생성된 소켓은 클라이언트의 소켓과 연결된 소켓임)
inet_ntoa() 는 client에서 사용한 inet_addr로 변환한 binary IP주소를 dotted_quad형식의 문자열로 다
시 변환한다.(정보를 print하기위해 사용하는 것 같음..)
TCP Echo Server
4. 다음과 같은 일을 계속적으로 반복
새롭게 생성된 클라이언트 소켓에 send() recv()를 호출하여 통신을 수행
char echoBuffer[RCVBUFSIZE];
int recvMsgSize;
recvMsgSize = recv(clntSock, echoBuffer, RCVBUFSIZE, 0)
send(clntSock, echoBuffer, recvMsgSize, 0)
client로부터 메세지를 받아서 그대로 다시 돌려주는 부분
위 에코 부분에 대한 함수 HandleTCPClient()라는 함수로 따로 분리되어있는데
서버 코드에서 응용 부분에 대한 자세한 내용을 분리시키는 것이 좋은 습관이라고 함.
TCP Echo Server
4. 다음과 같은 일을 계속적으로 반복
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740149(v=vs.85).aspx
close()를 통해 클라이언트와 연결 종료
closesocket(sock);
socket을 close한다.
여기서는 WSACleanup()이 없음.. 루프가 안 끝나서 그런가
TCP Echo Server
4. 다음과 같은 일을 계속적으로 반복
Client
TCP
SOCKET
TCP
PORT
IP
socket()
send()recv()
Server
TCP
SOCKET
TCP
PORT
IP
socket()
send()recv()
connect()
bind()
listen()
TCP
SOCKET
accept()
Conclusion

More Related Content

TCP echo 서버 및 클라이언트 예제 스터디

  • 1. TCP Echo Server & Client Basic example
  • 3. TCP Echo Client 1. Socket()을 이용하여 TCP Socket생성 2. connect()를 이용하여 서버와의 연결을 설정 3. send(), recv()를 이용하여 통신을 수행 4. close를 이용하여 통신 종료
  • 4. SOCKET 생성 WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) (sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) winsock의 경우 사용 전에 초기화를 해주어야 함(유닉스에서는 없는 부분) MAKEWORD(2,0)은 winsock 2.0을 쓰겠다는 뜻. IPPROTO_TCP라는 스트림 기반(SOCK_STREAM) 프로토콜을 이용하여 IPv4(PF_INET)에서 작동하도록 만들어진 소켓이라는 뜻. socket이라고 다 같은게 아니고 어떤 프로토콜을 사용할지 미리 설정하는 듯 TCP Echo Client 1. Socket()을 이용하여 TCP Socket생성 http://msdn.microsoft.com/en-us/library/windows/desktop/ms740506(v=vs.85).aspx
  • 5. SERVER 주소 구조체 생성 struct sockaddr_in echoServAddr; memset(&echoServAddr, 0, sizeof(echoServAddr)); echoServAddr.sin_family = AF_INET; echoServAddr.sin_addr.s_addr = inet_addr(servIP); echoServAddr.sin_port = htons(echoServPort); 주소 패밀리를 IPv4(AF_INET)로 지정하고, ip와 port번호를 설정 ( 유닉스에서는 inet_addr 대신 inet_pton 사용) inet_addr로 문자열을 binary로 변환 htons로 port번호도 변환한다. TCP Echo Client 1. Socket()을 이용하여 TCP Socket생성
  • 6. 연결 설정 connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) 만들어둔 socket과 socket구조체를 이용하여 연결을 설정 sockaddr_in 구조체가 IPv4를 위한 형식이고 connect에서는 범용적으로 사용할 수 있는 구조체인 sockaddr로 형변환 하여 사용한다. TCP Echo Client 2. connect()를 이용하여 서버와의 연결을 설정 http://msdn.microsoft.com/en-us/library/windows/desktop/ms740496(v=vs.85).aspx
  • 7. echo문자열을 서버로 전송 echoStringLen = strlen(echoString); send(sock, echoString, echoStringLen, 0) argv로 넘겨준 echoString과 echoStringLen을 이용하여 echo 문자열을 전송한다. send는 전송한 byte수를 return하며 echoStringLen과 비교하여 제대로 전송되었는지를 확인한다. TCP Echo Client 3. send(), recv()를 이용하여 통신을 수행
  • 8. echo 서버의 응답 수신 totalBytesRcvd = 0; printf("Received: "); while (totalBytesRcvd < echoStringLen) { if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0) DieWithError("recv() failed or connection closed prematurely"); totalBytesRcvd += bytesRcvd; echoBuffer[bytesRcvd] = '0'; printf("%s", echoBuffer); } 서버에서 보낸 메세지가 recv()가 받을 수 있는 크기보다 클 경우가 있으므로 while문을 돌면서 반복해서 데이터를 수신한다. recv()는 수신할 데이터가 있을 때까지 멈춰있는 block함수라 함 TCP Echo Client 3. send(), recv()를 이용하여 통신을 수행
  • 9. 연결 종료 closesocket(sock); WSACleanup(); /* Cleanup Winsock */ socket을 close한다. winsock의 경우 WSACleanup()으로 윈도우 소켓도 닫는다. TCP Echo Client 4. close를 이용하여 통신 종료
  • 10. TCP Echo Server 1. Socket()을 이용하여 TCP Socket생성 2. bind()를 통해 소켓에 포트 번호를 할당 3. listen()을 통해 해당 포트가 연결을 받아들이도록 시스템에 알림 4. 다음과 같은 일을 계속적으로 반복 1. accept()를 통해 각 클라이언트와 통신에 필요한 새로운 소켓을 획득 2. 새롭게 생성된 클라이언트 소켓에 send() recv()를 호출하여 통신을 수행 3. close()를 통해 클라이언트와 연결 종료
  • 11. SOCKET 생성 WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) (sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) winsock의 경우 사용 전에 초기화를 해주어야 함(유닉스에서는 없는 부분) MAKEWORD(2,0)은 winsock 2.0을 쓰겠다는 뜻. IPPROTO_TCP라는 스트림 기반(SOCK_STREAM) 프로토콜을 이용하여 IPv4(PF_INET)에서 작동하도록 만들어진 소켓이라는 뜻. socket이라고 다 같은게 아니고 어떤 프로토콜을 사용할지 미리 설정하는 듯 TCP Echo Server 1. Socket()을 이용하여 TCP Socket생성 ( client와 동일함 ) http://msdn.microsoft.com/en-us/library/windows/desktop/ms740506(v=vs.85).aspx
  • 12. SERVER 주소 구조체 생성 struct sockaddr_in echoServAddr; memset(&echoServAddr, 0, sizeof(echoServAddr)); echoServAddr.sin_family = AF_INET; echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); echoServAddr.sin_port = htons(echoServPort); IPv4를 사용 htons로 port번호 변환 와일드 카드 주소(INADDR_ANY)로 설정. 시스템에는 하나 이상의 IP주소가 있을 수 있는데 와일드 카드 주소로 설정하면 사용할 IP주소를 알아서 찾아준다고 하는 것 같음. 찾아보니 서버로 연결된 어떤 IP로 들어오든 (포트만 맞다면) 연결해준다는 얘기 TCP Echo Server 1. Socket()을 이용하여 TCP Socket생성 http://zerobell.tistory.com/5
  • 13. SOCKET을 지정한 IP주소 및 포트에 바인딩 bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) client는 connect()하기 위해 서버의 주소가 있어야 하고 server는 bind()하기 위해 자신의 주소가 필요함 위에서 지정한 주소 구조체(자신의 IP주소와 port에 대한 정보가 담긴)를 이용하여 socket과 bind()함 TCP Echo Server 2. bind()를 통해 소켓에 포트 번호를 할당 http://msdn.microsoft.com/en-us/library/windows/desktop/ms737550(v=vs.85).aspx
  • 14. SOCKET을 연결에 대한 대기상태로 전환 listen(servSock, MAXPENDING) listen()을 해주어야 연결 요청을 받을 수 있음 listen() 상태가 아닌 서버로의 (client의) connect()호출은 실패하게 된다. TCP Echo Server 3. listen()을 통해 해당 포트가 연결을 받아들이도록 시스템에 알림
  • 15. accept()를 통해 각 클라이언트와 통신에 필요한 새로운 소켓을 획득 clntLen = sizeof(echoClntAddr); clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, &clntLen printf("Handling client %sn", inet_ntoa(echoClntAddr.sin_addr)); listen() 상태에서 client의 접속이 감지되면 server에서는 아까 만들어둔 소켓으로 직접 통신을 하는 것 이 아니라, accept()를 이용하여 다른 소켓을 생성한다. accept()는 새로운 소켓의 식별자를 반환한다. (새로 생성된 소켓은 클라이언트의 소켓과 연결된 소켓임) inet_ntoa() 는 client에서 사용한 inet_addr로 변환한 binary IP주소를 dotted_quad형식의 문자열로 다 시 변환한다.(정보를 print하기위해 사용하는 것 같음..) TCP Echo Server 4. 다음과 같은 일을 계속적으로 반복
  • 16. 새롭게 생성된 클라이언트 소켓에 send() recv()를 호출하여 통신을 수행 char echoBuffer[RCVBUFSIZE]; int recvMsgSize; recvMsgSize = recv(clntSock, echoBuffer, RCVBUFSIZE, 0) send(clntSock, echoBuffer, recvMsgSize, 0) client로부터 메세지를 받아서 그대로 다시 돌려주는 부분 위 에코 부분에 대한 함수 HandleTCPClient()라는 함수로 따로 분리되어있는데 서버 코드에서 응용 부분에 대한 자세한 내용을 분리시키는 것이 좋은 습관이라고 함. TCP Echo Server 4. 다음과 같은 일을 계속적으로 반복 http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/windows/desktop/ms740149(v=vs.85).aspx
  • 17. close()를 통해 클라이언트와 연결 종료 closesocket(sock); socket을 close한다. 여기서는 WSACleanup()이 없음.. 루프가 안 끝나서 그런가 TCP Echo Server 4. 다음과 같은 일을 계속적으로 반복