그게 뭘까?
바로 linux 라이브러리들이다.
꽤 주요한 라이브러리 몇개가 없어서, 윈도우에서는 다른걸 쓴다.
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <conio.h>
#pragma comment(lib, "ws2_32.lib")
int main() {
char ip[] = "218.48.17.230";
int port = 10000;
int valread;
char *hello = (char*)"message from Client";
WSADATA wasData;
SOCKET hSock;
SOCKADDR_IN servAddr;
char recvmsg[1024];
WSAStartup(MAKEWORD(2, 2), &wasData);
hSock = socket(AF_INET, SOCK_STREAM, 0);
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(ip);
servAddr.sin_port = htons(port);
connect(hSock, (SOCKADDR*) &servAddr, sizeof(servAddr));
send(hSock, hello, strlen(hello), 0);
printf("Client Message sent\n");
valread = recv(hSock, recvmsg, sizeof(recvmsg) - 1, 0);
printf("%s\n", recvmsg);
closesocket은 소켓을 닫는 함수이다.
(hSock);
WSACleanup();
getch();
return 0;
}
stdio, stdlib은 이미 분석했으니 넘어가고
winsock2라는 헤더를 분석해보자.
winsock이란 windows socket API(WSA) 라는 API이다. 인터넷 네트워크와 소켓 관련 함수들을 제공해준다. 뒤의 2는 숫자 2이다.
내부에는 accept, bind, connect, htons, listen 등 우리가 linux에서 사용했던 함수들이 그래도 들어있지만, read, wrtie가 없어서 이건 쓸수 없다.
char ip[] = "218.48.17.230";
int port = 10000;
int valread;
char *hello = (char*)"message from Client";
WSADATA wasData;
SOCKET hSock;
SOCKADDR_IN servAddr;
char recvmsg[1024];
wsadata 구조체이다.
typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
#if ...
unsigned short iMaxSockets;
#if ...
unsigned short iMaxUdpDg;
#if ...
char *lpVendorInfo;
#if ...
char szDescription[WSADESCRIPTION_LEN + 1];
#if ...
char szSystemStatus[WSASYS_STATUS_LEN + 1];
#else
char szDescription[WSADESCRIPTION_LEN + 1];
#endif
#else
char szSystemStatus[WSASYS_STATUS_LEN + 1];
#endif
#else
unsigned short iMaxSockets;
#endif
#else
unsigned short iMaxUdpDg;
#endif
#else
char *lpVendorInfo;
#endif
} WSADATA;
내부 내용들은 다음과 같다.
wVersion
wHighVersion
szDescription
iMaxSockets
iMaxUdpDg
소켓을 생성한다.
앞에서 자주 본 그 구조체이다.
대충 알아봤으니, 이제 함수를 분석해보자.
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
윈도우 소켓에서 특징적인 점은 위 함수로 시작한다는 점이다.
이 함수는 winsock 고나련 라이브러리를 초기화하고 데이터를 넣어줄때 쓰인다.
wVersionRequest는 MAKEWORD라는 함수를 받는다.
MAKEWORD(1,2) // 주 버전 1 부 버전 2 0x0201
MAKEWORD(2,2)// 주 버전 2, 부 버전 2 0x0202
따라서 이 함수의 실 사용례는 다음과 같다.
WSAStartup(MAKEWORD(2, 2), &wasData);
그 외의 처리는 linux client와 동일하다. memset으로 메모리를 초기화하여 addr 구조체를 채우고, connect 하고 send recv 한다. closesocket은 소켓을 닫는 함수이다.
winsock 라이브러리를해체하는 함수이다.
cmd에서 g++로 이걸 실행시키려 하면 네트워크 관련 각종 함수나 타입들을 정의할수 없다고 에러가 발생한다.
따라서 이를 방지하기 위해
#pragma comment(lib, "ws2_32.lib")
을 써주고 동시에 cmd에서 컴파일할때도
gcc -o client client.cpp -lws2_32
를 써서 컴파일 해주면 된다.
리눅스쪽은
g++ -o linux_server linux_server.cpp
이렇게 서로 메세지를 주고받은것을 알 수 있다.
참고로 server는 어차피 둘다 linux에서 작동하도록 짜여진코드라서 어떤 코드를 써도 작동한다.
문제가 하나 있다. 채팅 프로그램을 만들려면 일단 cpp 멀티스레딩부터 익혀야한다...
다음주부터 spring 학습 및 실습도 들어가야하니 아마 실제로 채팅프로그램을 만드는건 더 오래걸릴지도 모르겠다.