TCP/IP 소켓 프로그래밍 2판(한빛아카데미, 2022) 연습문제 풀이
Q 4_4. TCPServer/TCPClient 예제를 수정하여, 클라이언트에서 32비트 정수 두 개를 입력받아 보내면 서버에서 두 수의 합을 계산하여 숫자 형태로 리턴하도록 하시오.
A: TCPServer.cpp
#include "..\..\Common.h"
#define SERVERPORT 9000
#define BUFSIZE 512
int main(int argc, char *argv[])
{
..
// 데이터 통신에 사용할 변수
..
// 입력 정수 변수 추가
int num1 = 0;
int num2 = 0;
while (1) {
..
while (1) {
// 데이터 받기
..
// 받은 데이터 출력
..
// 첫 번째 입력 숫자를 정수로 변환(32비트 정수 - 스페이스 아스키 코드 32까지 정수로)
num1 = atoi(buf);
printf("%d ", num1);
// 두 번째 입력 숫자를 정수로 변환(32비트 정수로)
// 스페이스바 위치를 찾은 후 그 위치부터 반환
char* ptr = strchr(buf, 32);
num2 = atoi(ptr);
printf("%d ", num2);
// num1 + num2 -> 문자열로 변환
_itoa(num1 + num2, buf, 10);
// 데이터 보내기
retval = send(client_sock, buf, retval, 0);
if (retval == SOCKET_ERROR) {
err_display("send()");
break;
}
}
..
}

Q 4_6. TCPServer/TCPClient 예제를 수정하여, 클라이언트에서 32비트 정수 한 개를 입력받아 보내면 서버에서 이 숫자의 이진수 표현을 문자열 형태로 리턴하도록 하시오.
A:
1) TCPServer.cpp
int main(int argc, char* argv[])
{
..
// 데이터 통신에 사용할 변수
..
int num1 = 0;
while (1) {
// accept()
..
// 클라이언트와 데이터 통신
while (1) {
// 데이터 받기
..
// 받은 데이터 출력
..
// 첫 번째 입력 숫자를 정수로 변환(32비트 정수 - 스페이스 아스키 코드 32까지 정수로)
num1 = atoi(buf);
printf("[서버] 받은 숫자: %d\n", num1);
// 32비트 정수를 2진수로 변환
char bin[33]; // 32비트 + NULL 종료 문자
_itoa(num1, bin, 2); // 정수를 2진수 문자열로 변환
// 받은 숫자의 이진수 표현 출력
printf("[서버] %d 의 이진수 표현: %s\n", num1, bin);
// 이진수 문자열 전송
retval = send(client_sock, bin, strlen(bin), 0); // 이진수 전송
if (retval == SOCKET_ERROR) {
err_display("send() - 이진수 전송");
break;
}
}
..
}
2) TCPClient.cpp
int main(int argc, char* argv[])
{
..
// 데이터 통신에 사용할 변수
..
int num;
// 서버와 데이터 통신
while (1) {
// 데이터 입력
..
// '\n' 문자 제거
..
num = atoi(buf);
// 데이터 보내기
retval = send(sock, buf, (int)strlen(buf), 0);
if (retval == SOCKET_ERROR) {
err_display("send()");
break;
}
printf("[TCP 클라이언트] %d바이트를 보냈습니다.\n", retval);
// 데이터 받기 - 2진수 받기로 수정
retval = recv(sock, buf, BUFSIZE, 0);
if (retval == SOCKET_ERROR) {
err_display("recv()");
break;
}
else if (retval == 0)
break;
// 받은 데이터 출력
buf[retval] = '\0';
printf("[TCP 클라이언트] %d바이트를 받았습니다.\n", retval);
printf("[받은 데이터] %s\n", buf);
}
..
}

Q 4_8. TCP 클라이언트에서 connect() 함수를 호출하기 전에 bind() 함수를 호출하면 TCP 서버와 마찬가지로 사용할 포트 번호를 고정할 수 있다. TCPClient 예제를 수정하여, 항상 포트 번호 50000을 사용하도록 하시오. 또한 이처럼 구현할 때 어떤 문제가 있을지 논의하시오.
A:(4, 6번 사진 포트 번호 보면 매번 바뀜 이를 50000으로 고정하도록 수정)
- TCPClient.cpp
#include "..\..\Common.h"
char* SERVERIP = (char*)"127.0.0.1";
#define SERVERPORT 9000
#define CLIENTPORT 50000 // 고정 포트 번호 추가
#define BUFSIZE 512
int main(int argc, char* argv[])
{
int retval;
..
// 클라이언트의 포트 번호 고정 (bind 사용)
struct sockaddr_in clientaddr;
memset(&clientaddr, 0, sizeof(clientaddr));
clientaddr.sin_family = AF_INET;
clientaddr.sin_addr.s_addr = htonl(INADDR_ANY);
clientaddr.sin_port = htons(CLIENTPORT); // 고정 포트 번호
retval = bind(sock, (struct sockaddr*)&clientaddr, sizeof(clientaddr));
if (retval == SOCKET_ERROR) {
err_display("bind()");
closesocket(sock);
WSACleanup();
return 1;
}
// 서버 연결
..
// 데이터 통신에 사용할 변수
..
..
// 소켓 닫기
..
// 윈속 종료
..
}

- 포트 번호 고정시 문제점
1) 포트 충돌 가능성
2) 클라이언트와 서버 간 포트 번호 조정 필요
3) NAT 및 방화벽 문제 발생 가능
'네트워크 프로그래밍 > 연습문제' 카테고리의 다른 글
| [네트워크 프로그래밍] 3장 연습문제 (0) | 2024.09.26 |
|---|---|
| [네트워크 프로그래밍] 2장 연습문제 (0) | 2024.09.20 |
| [네트워크 프로그래밍] 1장 연습문제 (0) | 2024.09.20 |