kakasoo

[TCP/IP] 윈도우 소켓 간 통신 (cmd 창에서 확인하기) 본문

프로그래밍/네트워크

[TCP/IP] 윈도우 소켓 간 통신 (cmd 창에서 확인하기)

카카수(kakasoo) 2020. 7. 15. 12:25
반응형
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <WinSock2.h>
#include <stdlib.h>
#include <stdio.h>
 
void ErrorHandling(const char* message) {
    fputs(message, stderr); // buffer 문제를 없애기 위해서 stderr를 전달 => 기본출력장치(모니터), 에러
    fputc('\n', stderr);
}
 
// argc == 옵션의 개수
// argv == 옵션의 값, 명칭
int main(int argc, char* argv[]) {
    
    WSADATA wsaData;
    SOCKET hServSock, hClntSock;
    SOCKADDR_IN servAddr, clntAddr; // server와 client socket을 만들고 주소 변수도 생성했다.
 
    int szClntAddr;
    char message[] = "hello World!"// 보내고 싶은 메시지를 배열에 저장하였다.
 
    if (argc != 2) {
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }
 
    if (WSAStartup(MAKEWORD(22), &wsaData) != 0// WSA를 start한다.
        ErrorHandling("WSAStartup() error!");
 
    hServSock = socket(PF_INET, SOCK_STREAM, 0); // PF_INET = IPv4의 프로토콜
    if (hServSock == INVALID_SOCKET) // socket() 함수는 SOCKET 구조체 또는 Error 값을 반환한다.
        ErrorHandling("socket() error!");
 
    memset(&servAddr, 0sizeof(servAddr)); // servAddr을 모두 0으로 초기화하였다.
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servAddr.sin_port = htons(atoi(argv[1])); // 주소 설정하는 방법은 추후에.
 
    if (bind(hServSock, (SOCKADDR*&servAddr, sizeof(servAddr)) == SOCKET_ERROR) // 소켓에 주소 할당
        ErrorHandling("bind() error!");
 
    if (listen(hServSock, 5== SOCKET_ERROR)
        ErrorHandling("listen() error!");
    
    szClntAddr = sizeof(clntAddr);
    hClntSock = accept(hServSock, (SOCKADDR*)&clntAddr, &szClntAddr); // hClntSock을 ServSock에 접근 허용
    if (hClntSock == INVALID_SOCKET)
        ErrorHandling("accept() error!");
 
    send(hClntSock, message, sizeof(message), 0); // 클라이언트에 데이터를 전송한다.
    closesocket(hClntSock);
    closesocket(hServSock);
    WSACleanup();
    return 0;
}
cs

 

저번에 빠져 있던 listen() 함수를 포함해서 다시 작성한 것이다.

이것을 컴파일해서 c 파일을 만들어보자.

나는 이 파일의 실행 파일을 visual studio 폴더에서 꺼내서, desktop으로 옮길 것이다. (나는 해당 폴더에서는 막힌다.)

 

 

일단 내 이름을 지우고, 스크린샷을 찍은 건데, 보시다시피 해당 주소로 간다.

나는 socket과 socket2 라는 이름의 exe file이 있는데, socket은 listen()을 빼먹었을 당시의 파일이고,

socket2는 listen()을 넣은 다음의 모습이다.

단순히 socket2 라고만 입력할 게 아니라, socket2 <port number>의 꼴로 입력을 해야 했다.

이는 main(int argc, char* argv[])의 꼴이기 때문에, 우리가 main()함수를 시작하기 전에 매개변수를 넣을 수 있음이다.

 

argv[0]은 자동적으로 이 실행파일의 시작 위치가 나올 것이고 (아마도, 나는 파일을 옮겨서 정확한 위치는 모르겠다.)

argv[1]는 방금 내가 넣은 9180이라는 port 번호가 들어 가게 된다.

따라서 argc는 2가 된다. (argc는 main 함수의 매개 변수가 몇 개인지를 의미하는 int형 변수이기 때문에)

잘 보면, 명령 프롬프트의 상태 바가 socket2 9180으로 되있는 걸 볼 수 있는데, 이는 화면이 마냥 멈춰 있지 않다는 것을 간접적으로 보여주는 셈이다.

아직 hello world! 를 출력받을, 클라이언트 소켓의 접근이 없어서, accept() 단계에서 마냥 멈춰 있는 셈이다.

이제 다른 cmd 창으로, 클라이언트 socket을 작동시켜보자.

 

다른 cmd창에서 "클라이언트 소켓.exe 127.0.0.1 9180" 이라고 입력해보자.

클라이언트 소켓 이름과, 자신의 IP 주소, 그 다음에 서버의 포트 번호와 동일한 포트 번호를 입력하면 hello world가 나온다.

반응형