급하게 만듬
아직 더 고쳐야 함
#include "stdio.h"
#include "winsock2.h"
#include <string>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
#define DESIRED_WINSOCK_VERSION 0x0202
#define MINIMUM_WINSOCK_VERSION 0x0001
#define MAXMSGBUFSIZE 1024
#define MAXWAITBUFSIZE 4096
// 메세지 타입
#define ODSP_COMMAND 1
#define ODSP_REQUEST 2
#define ODSP_ACK 3
#define ODSP_ECHO 4
#define ODSP_END 5
// 메세지 헤더
struct ODSP_HDR
{
unsigned int msgType;
unsigned int msgLen;
};
using namespace std;
int main()
{
// 대기 버퍼에서 헤더를 분석할 순서 인지를 판별하기 위한 변수
bool isHeader = true;
// client 종료
bool isExit = false;
// 현재 대기 버퍼에 있는 데이터 길이
unsigned int curLen = 0;
// 보낸 메세지 길이
unsigned int sentMsgLen = 0;
//받은 메세지 길이
unsigned int receivedMsgLen = 0;
// 입력된 메세지를 스트링으로 받는다.
// 메세지의 길이 확인용
string Msg = "";
// 보낼 메세지 버퍼
char bufMsg[MAXMSGBUFSIZE] = {0, };
// 받은 메세지 대기 버퍼
char bufWait[MAXWAITBUFSIZE] = {0, };
// receive 버퍼
char bufRecv[MAXMSGBUFSIZE] = {0, };
// send 버퍼
char bufSend[MAXMSGBUFSIZE] = {0, };
// 받은 헤더 처리 버퍼
char bufHdr[MAXMSGBUFSIZE] = {0, };
// 받은 메세지 처리 버퍼
char bufRecvMsg[MAXMSGBUFSIZE] = {0, };
// 대기 버퍼 스왑용 버퍼
char bufTemp[MAXWAITBUFSIZE] = {0, };
// send 버퍼 인덱스 포인터
char *ptrSendBufIdx = 0;
// 대기 버퍼 인덱스 포인터
char *ptrRecvBufIdx = 0;
// data 정리용 포인터 선언
char *ptrDataSortingIdx = 0;
// 메세지 헤더 구조체 선언
ODSP_HDR hdr;
// receive 헤더 구조체 포인터 선언
ODSP_HDR recv_hdr;
// client 소켓 선언
SOCKET clientSock;
WSADATA wsadata;
// 서버주소 구조체 변수 선언
struct sockaddr_in server_addr;
// 소켓을 초기화
if(!WSAStartup(DESIRED_WINSOCK_VERSION, &wsadata))
{
if(wsadata.wVersion < MINIMUM_WINSOCK_VERSION)
{
WSACleanup();
exit(1);
}
}
// client 소켓 생성
// AF_INET -> ipv4를 의미, PF를 접두사(예: PF_INET)로 쓰는 경우도 있으나 예전 방식
// SOCK_STREAM -> TCP를 의미, SOCK_DGRAM -> UDP 등
// 0 -> SOCK_STREAM으로 프로토콜이 이미 정의 되었음을 의미
clientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(clientSock == INVALID_SOCKET)
{
cout << endl << "socket error : " ;
//printf("socket error : ");
WSACleanup();
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
// 서버 주소 지정
// AF_INET -> ipv4
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("192.168.1.182");
server_addr.sin_port = htons(30000);
// 서버에 접속 요청
// 서버는 listen 하고 있다가 접속요청을 받고 3-way handshake
if(connect(clientSock, (LPSOCKADDR)&server_addr, sizeof(server_addr)) != 0)
{
cout << endl << "connect error : " ;
//printf("connect error : ");
exit(1);
}
ptrRecvBufIdx = bufWait;
while(true)
{
// message type을 입력 받음
cout << endl << "1 - COMMAND" << endl;
cout << "2 - REQUEST" << endl;
cout << "3 - ACK" << endl;
cout << "4 - ECHO" << endl;
cout << "5 - END" << endl;
cout << "input message type : " ;
// 헤더구조체의 메세지 타입에 입력
cin >> hdr.msgType;
//cin.clear();
//cout.clear();
cout << "input message : " ;
//cin >> bufMsg;
cin.getline(bufMsg, 1024, '\n');
cin.clear();
getline(cin, Msg);
//Msg = bufMsg;
hdr.msgLen = Msg.length();
strcpy(bufMsg, Msg.c_str());
// 헤더와 메세지를 결합
ptrSendBufIdx = bufSend;
memcpy(ptrSendBufIdx, &hdr, sizeof(hdr));
ptrSendBufIdx = ptrSendBufIdx+sizeof(hdr);
memcpy(ptrSendBufIdx, bufMsg, hdr.msgLen);
// 메세지 전송
if(sentMsgLen = send(clientSock, bufSend, sizeof(hdr) + hdr.msgLen, 0) < 0)
{
cout << endl << "send error!!" << endl;
return 0;
}
if(hdr.msgType == ODSP_END)
{
break;
}
if(hdr.msgType == ODSP_COMMAND || hdr.msgType == ODSP_ECHO)
{
// 메세지 수신
while(true)
{
memset(bufRecv, 0, sizeof(bufRecv));
// 메세지 수신
receivedMsgLen = recv(clientSock, bufRecv, MAXMSGBUFSIZE, 0);
if(receivedMsgLen >= 0)
{
memcpy(ptrRecvBufIdx, bufRecv, receivedMsgLen);
curLen += receivedMsgLen;
ptrRecvBufIdx += receivedMsgLen;
receivedMsgLen = 0;
// 헤더를 분석할 순서
if(isHeader)
{
// 헤더 길이 이상의 data가 있는지 확인
//if(curLen >= sizeof(recv_hdr))
if(curLen >= sizeof(hdr))
{
memset(bufHdr, 0, sizeof(bufHdr));
//memcpy(bufHdr, bufWait, sizeof(recv_hdr));
memcpy(bufHdr, bufWait, sizeof(hdr));
//bufHdr[sizeof(recv_hdr)] = '\0';
bufHdr[sizeof(hdr)] = '\0';
memcpy(&recv_hdr, bufHdr, sizeof(recv_hdr));
//recv_hdr = (ODSP_HDR*)bufHdr;
// 버퍼의 data를 정리
ptrDataSortingIdx = bufWait + sizeof(recv_hdr);
memset(bufTemp, 0, sizeof(bufTemp));
memcpy(bufTemp, ptrDataSortingIdx, sizeof(bufWait) - sizeof(recv_hdr));
memset(bufWait, 0, sizeof(bufWait));
memcpy(bufWait, bufTemp, sizeof(bufTemp));
curLen -= sizeof(recv_hdr);
ptrRecvBufIdx -= sizeof(recv_hdr);
isHeader = false;
}
}
if(!isHeader)
{
// 분석된 헤더의 메세지 길이 정보를 통해 현재 버퍼에 메세지 길이 이상의 data가 있는지 확인
if(curLen >= recv_hdr.msgLen)
{
memset(bufRecvMsg, 0, sizeof(bufRecvMsg));
memcpy(bufRecvMsg, bufWait, recv_hdr.msgLen);
bufRecvMsg[recv_hdr.msgLen] = '\0';
// 버퍼의 data를 정리
ptrDataSortingIdx = bufWait + recv_hdr.msgLen;
memset(bufTemp, 0, sizeof(bufTemp));
memcpy(bufTemp, ptrDataSortingIdx, sizeof(bufWait) - recv_hdr.msgLen);
memset(bufWait, 0, sizeof(bufWait));
memcpy(bufWait, bufTemp, sizeof(bufTemp));
curLen -= recv_hdr.msgLen;
ptrRecvBufIdx -= recv_hdr.msgLen;
isHeader = true;
if(recv_hdr.msgType == ODSP_COMMAND)
{
cout << endl << "received command message" << endl;
cout << "message length is " << recv_hdr.msgLen << "byte" << endl;
cout << "receive message : " << bufRecvMsg << endl;
break;
}
else if(recv_hdr.msgType == ODSP_REQUEST)
{
cout << endl << "received request message" << endl;
cout << "message length is " << recv_hdr.msgLen << "byte" << endl;
cout << "receive message : " << bufRecvMsg << endl;
break;
}
else if(recv_hdr.msgType == ODSP_ACK)
{
cout << endl << "received ack message" << endl;
cout << "message length is " << recv_hdr.msgLen << "byte" << endl;
cout << "receive message : " << bufRecvMsg << endl;
break;
}
else if(recv_hdr.msgType == ODSP_ECHO)
{
cout << endl << "received echo message" << endl;
cout << "message length is " << recv_hdr.msgLen << "byte" << endl;
cout << "receive message : " << bufRecvMsg << endl;
break;
}
else if(recv_hdr.msgType == ODSP_END)
{
cout << endl << "received end message" << endl;
cout << "message length is " << recv_hdr.msgLen << "byte" << endl;
cout << "receive message : " << bufRecvMsg << endl;
isExit = true;
break;
}
else
{
cout << endl << "received unknown message" << endl;
cout << "exit client" << endl;
return 0;
}
}
}
}
else
{
break;
}
}
}
}
// 소켓을 닫음
closesocket(clientSock);
cout << "client exit" << endl;
return 0;
}