// Server
#include<WinSock2.h>
#include<mswsock.h>
#include<ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
void HandleError(const char* cause)
{
int32 err = WSAGetLastError();
cout << cause << err << " : error exists";
}
int main()
{
WSADATA wsaData;
int32 err;
err = ::WSAStartup(MAKEWORD(2, 2), &wsaData);
if (err != 0)
{
cout << "Winsock Initialize Failed\n" << err << " : error exists";
return 0;
}
SOCKET serverSocket = ::socket(AF_INET, SOCK_DGRAM, 0);
if (serverSocket == INVALID_SOCKET)
{
HandleError("Socket Failed");
return 0;
}
SOCKADDR_IN serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = ::htonl(INADDR_ANY);
serverAddr.sin_port = ::htons(7777);
err = ::bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if (err == SOCKET_ERROR)
{
HandleError("Bind failed");
return 0;
}
while (true)
{
char recvBuffer[1000];
SOCKADDR_IN clientAddr;
int addrLen = sizeof(clientAddr);
::memset(&clientAddr, 0, sizeof(clientAddr));
int32 recvLen = ::recvfrom(serverSocket, recvBuffer, sizeof(recvBuffer), 0, (SOCKADDR*)&clientAddr, &addrLen);
if (recvLen <= 0)
{
HandleError("RecvFrom Failed");
return 0;
}
cout << "Recv Data! Data = " << recvBuffer << endl;
cout << "Recv Data! Len=" << recvLen << endl;
err = ::sendto(serverSocket, recvBuffer, sizeof(recvBuffer), 0, (SOCKADDR*)&clientAddr, sizeof(clientAddr));
if (err == SOCKET_ERROR)
{
HandleError("Send Failed");
return 0;
}
}
return 0;
}
#include "pch.h"
#include <CorePch.h>
#include <WinSock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
void HandleError(const char* cause)
{
int32 err = WSAGetLastError();
cout << cause << err << " : error exists";
}
int main()
{
// 전체적인 흐름
// wsastartup(초기화) -> socket 준비 -> socket addr 준비 -> connect -> wsacleanup()
WSADATA wsData;
// winsock을 사용할 준비가 되었다(ws2_32 라이브러리 초기화)
// parameter
// 1. winsock 버전
// 2. winsock 관련 정보가 wsData에 채워짐
// 성공시 return 값이 0임
int err = ::WSAStartup(MAKEWORD(2, 2), &wsData);
if (err != 0)
{
cout << "WSAStartUp initialize failed\n" << err << " : error exists";
return 0;
}
// 전화를 걸 전화기 생성 ( 이 socket을 이용해 데이터 전송 )
// parameter
// 1. 주소체계(IPv4 / IPv6) -> 네트워크 주소 할당의 문제로 새로운 주소 체계 편입
// AF_INET(IPv4 주소 체계)
// AF_INET(IPv6 주소 체계)
// 2. socket type (TCP / UDP)
// SOCK_STREAM(TCP활용) / SOCK_DGRAM(UDP활용)
// 신뢰성 / 비신뢰성(패킷 소실의 위험성이 있음)
// 왠만하면 TCP 사용
// 3. protocol은 0으로 입력(default값)
// return : descriptor를 return 함
SOCKET clientSocket = ::socket(AF_INET, SOCK_DGRAM, 0);
if (clientSocket == INVALID_SOCKET)
{
HandleError("Socket Failed");
return 0;
}
// 식당 번호 입력
SOCKADDR_IN serverAddr; // IPv4 용
// SOCKADDR_IN6 IPv6용
::memset(&serverAddr, 0, sizeof(serverAddr));
// IPv4용이기때문에 항상 AF_INET을 설정해야함
serverAddr.sin_family = AF_INET;
// 주소체계는 1바이트씩 끊어서 사용 2^8 -> 256까지
// inet_addr은 너무 구식
// serverAddr.sin_addr.S_un.S_addr = ::inet_addr("192.168.123.100");
// 127.0.0.1 루프백 주소(내 자신의 컴퓨터 ip)
// 나중에는 DNS를 활용
::inet_pton(AF_INET, "127.0.0.0", &serverAddr.sin_addr);
// 포트 번호 연결할 목적지는? ( IP주소 + Port )-> IP아파트 Port 동
// 일부 번호는 예약 되어있기 때문에 port는 이왕이면 10000번대를 넘어서 등록하면 좋다
// htons
// host to network short
// network to host short
// Little-Endian vs Big-Endian
// ex) 0x12345678 4바이트 정수
// [0x78][0x56][0x34][0x12] <- little
// [0x12][0x34][0x56][0x78] <- big
// 요즘 대부분은 리틀엔디안 사용(intel corp.)
// network에서는 빅엔디안을 사용함
serverAddr.sin_port = ::htons(7777);
while (true)
{
// TODO
// 어떤 핸드폰으로 무엇을 보낼지!
// parameter
// 1. socket
// 2. buf(실제 데이터)
// 3. 버퍼 크기
// 4. flag (default 0 다른 옵션 가능)
char sendBuffer[100];
cin >> sendBuffer;
int32 resultCode = ::sendto(clientSocket, sendBuffer, sizeof(sendBuffer), 0, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if (resultCode == SOCKET_ERROR)
{
int32 errCode = ::WSAGetLastError();
cout << "Send ErrCode : " << errCode << endl;
return 0;
}
cout << "Send Data! Len = " << sizeof(sendBuffer) << endl;
char recvBuffer[1000];
int addrLen = sizeof(serverAddr);
err = ::recvfrom(clientSocket, recvBuffer, sizeof(recvBuffer), 0,(SOCKADDR*)&serverAddr,&addrLen);
if (err == SOCKET_ERROR)
{
err = ::WSAGetLastError();
cout << "Recv ErrorCode : " << err << endl;
return 0;
}
cout << "Echo Recv Data! Len = " << err << endl;
cout << "Echo Recv Data! Data = " << recvBuffer << endl;
}
// 소켓 리소스 반환
::closesocket(clientSocket);
// winsock 해제
::WSACleanup();
}
Unconnected UDP
recvfrom()
sendto()
Connected UDP
::connect() 함수 사용(주소 등록)
recv()
send()