본문 바로가기
IT창고/Network

간단한 계산을 하는 서버 / 클라이언트

by 창구창고 2007. 1. 22.
반응형

//CalServer.h
#pragma pack( 1 )

enum { PLUS = '+', MINUS = '-', MULTIPLY = '*', DIVIDE = '/' } ;

typedef struct _CALCPACKET
{
int cmd;
int first;
int second;

}CALCPACKET;




#define WIN32_LEAN_AND_MEAN // windows.h 에서 자주 사용하지 않는 것은 컴파일에서 제외한다.
							// winsock2.h 와의 충돌을 막아준다.

#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <stdlib.h>
#pragma comment(lib, "ws2_32.lib")
#include "CalServer.h"

void main(int argc, char** argv)
{
	if (argc != 4)
	{
		printf("usage : ClaClient <first number> <+,-,*,/> <second number>\n");
		return;
	}

	int first	= atoi(argv[1]);
	int second	= atoi(argv[3]);
	int cmd	= (int)argv[2][0];

	WSADATA wsadata;

	if( WSAStartup(MAKEWORD(2,2), &wsadata) != 0)
	{
		printf("Can't Initialize Socket !\n");
		return;
	}
	//--------------------------------------------------------------

	SOCKET s = socket(AF_INET, SOCK_STREAM, 0);

	SOCKADDR_IN addr = {0};
	addr.sin_family	= AF_INET;
	addr.sin_port	= htons( 4000);
	addr.sin_addr.s_addr = inet_addr("61.81.99.54");

	if(connect(s, (SOCKADDR*)&addr, sizeof(addr)) == -1)
	{
		printf("서버에 접속할수 없음\n");
		return;
	}

	//서버에 패킷을 보냄
	CALCPACKET packet = {cmd, first, second};

	send(s, (char*)&packet, sizeof(packet),0);

	//돌아오는 패킷 수신
	int total = sizeof(packet); // 수신해야 하는 크기
	int current = 0;	// 현재 수신한 총 크기
	int nRead = 0;
	
	while(total < current) // 아직 다 받지 못한경우
	{
		nRead = recv(s, (char*)&packet + current, total - current,  0);
		
		if(nRead > 0)
		{
			current += nRead;
			continue; // 계속 수신한다.
		}
		else if(nRead == 0) // 접속이 끊어 진 경우
		{
			break;
		}
		else if(nRead < 0 ) // 수신 에러 발생
		{
			break;
		}
	}
	//recv(s, (char*)&packet, sizeof(packet),0);

	printf("결과 : %d \n", packet.first);

	closesocket(s);
}
 
 
#include "CalServer.h"
#define WIN32_LEAN_AND_MEAN // windows.h 에서 자주 사용하지 않은 것은 컴파일에서 제외 한다.
							// winsock2.h외의 충돌을 막아 준다.

#include<stdio.h>
#include<windows.h>
#include<winsock2.h>
#include<vector>// STL의 vector
using namespace std;

#pragma comment(lib, "ws2_32.lib")
DWORD WINAPI MessageFun(void * mes)
{
	SOCKET s  = (SOCKET)mes;

	//클라이언트가 보내는 구조체를 수신한다.
	CALCPACKET packet;

	int total = sizeof(packet); // 수신해야 하는 크기
	int current = 0;	// 현재 수신한 총 크기
	int nRead = 0;
	
	while(total < current) // 아직 다 받지 못한경우
	{
		nRead = recv(s, (char*)&packet + current, total - current,  0);
		
		if(nRead > 0)
		{
			current += nRead;
			continue; // 계속 수신한다.
		}
		else if(nRead == 0) // 접속이 끊어 진 경우
		{
			break;
		}
		else if(nRead < 0 ) // 수신 에러 발생
		{
			break;
		}
	}
	//연산을 수행한다.
	int sum = 0;
	switch(packet.cmd)
	{
	case PLUS		:	sum = packet.first + packet.second; break;
	case MINUS		:	sum = packet.first - packet.second; break;
	case DIVIDE		:	sum = packet.first / packet.second; break;
	case MULTIPLY	:	sum = packet.first * packet.second; break;
	}

	//결과를 first에 넣어서 돌려준다.
	packet.first = sum;

	send(s, (char *)&packet, sizeof(packet), 0);

	closesocket(s);
	return 0;
}

void main()
{
	WSADATA wsadata;

	//if(WSAStartup(0x0202, &wsadata) != 0)			//0x0202는 뒤에서부터 읽어서 2.2버젼을 쓰라는 이야기다.
	if(WSAStartup(MAKEWORD(2,2), &wsadata) != 0)	//많이 사용... 앞에서 부터 읽는다.
	{
		printf("Can't Initialize Socket !\n");
		return ;
	}
	//------------------------------------------
	//1. socket생성 : TCP: SOCK_STREAM : UDP :SOCK_DGRAM
	SOCKET s = socket(AF_INET,  SOCK_STREAM, 0);

	//2. 생성된 소켓에 주소를 지정.
	SOCKADDR_IN addr = { 0 };
	addr.sin_family = AF_INET;	// 주소 종류 (AF_INET : IP 주소라는 의미..
	addr.sin_port = htons(4000);	//Port #
	addr.sin_addr.s_addr = inet_addr("61.81.99.54");
	
	if(bind(s,(SOCKADDR*)&addr, sizeof(addr)) == -1)	//서버의 닫혀 있는 상태를 대기 상태로 바꿔준다. 이순간 소켓은 내부적으로 접속요청 큐와 접속 완료 큐가 만들어진다.
	{
		printf("Can't bind \n"); 
		return;
		
	}
	
	//3. 소켓을 대기 상태로 전환한다.
	if(listen(s, 5) == -1)
	{
		printf("Can't Listen\n");
		return;
	}
	
	printf("클리이언트를 대기합니다. \n");
	
	//4. 이제 Client 에서 부터 전달된 요청을 허용한다.
	while(1)
	{
		SOCKADDR_IN c_addr;
		int size = sizeof(c_addr);
		
		SOCKET c_s = accept(s, (SOCKADDR*)&c_addr, &size);	//억셉트를 눌렀는데 대기 큐에 아무도 없으면 대기한다.
		//억셉트를 누르는 순간 새로운 소켓을 만들어서 
		//상태를 연걸상태로 
		//IP는 자신의 IP로 포트는 놀고있는 임의의 포트로 설정해준다.->4000번 포트로 접속해서 다른포트로 통신
		//상대 IP와 상대 포트를 지정... 상대의 포트도 접속후에는 통신하는 포트로 지정한다.
		//->접속하는 소켓은 대기만하고 접속하면 새로운 소켓이 통신을 한다.
		
		printf("클라이언트가 접속했습니다. IP : %s\n", inet_ntoa(c_addr.sin_addr));

		
		//새로운 스레드를 생성해서 클라이언트의 요청을 처리한다.
		HANDLE hThread = CreateThread(0 , 0, MessageFun, (void *)c_s, 0,0);
		CloseHandle(hThread);
	}
	
	//---------------------------------------------------------------------------
	closesocket(s); // 소켓 닫기
	
	//--------------------------------------------------------------
	
	//------------------------------------------
	WSACleanup();
}
반응형

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."