스레드(Thread)
프로세스의 코드를 수행하는 단위이다. 한 프로세스당 복수개의 스레드를 허용함으로써 분리된 개념으로 생각되었음. 즉 스레드를 프로세스에 속하는 자원의 일종으로 생각할수 있다.
프로세스(Process)혹은 태스크(Task)
프로세스란 쉽게 생각하면,흔히 윈도우즈에서 실행 중인 파워포인트,MP3 플레이어,아래아 한글 등
이러한 개개의 프로그램을 일컫는다.프로세스가 하드디스크상에 있는 이러한 프로그램 이미지가
아니라 '실행중'인 프로그램을 가리킨다..
WaitForSingleObject()
Win32 프로세스 대기함수. Win32 프로세스, Windows 16비트 프로세스 및 MS-MS-DOS 기반 응용 프로그램을 종료할 때까지 기다립니다.
ws2_32.lib
윈도우와 인터넷을 연결하는 소켓에 관한 32비트 파일을 모아놓은 라이브러리
동기화
다중 스레드가 실행되는 상황에서 스레드 마다의 실행순서를 제어해서 경쟁 상태나 교착 상태를 해소하는 것을 동기화라고 한다.
경쟁상태: 둘이상의 스레드가 공유 자원을 서로 사용하려는 상태
교착상태: 스레드끼리 서로를 기다리며 블럭된 상태
소켓 주소 구조체(SOCKADDR)
소켓 프로그래밍에서 클라이언트 또는 서버의 구체적인 주소를 표현하기 위해서는 주소체계(address family),IP주소,포트 번호 세가지로 지정되어야 하며 3가지 정보를 묶어서 소켓 주소라고 부른다.
sockaddr_in 구조체 4바이트의 IP주소와 2바이트의 포트번호를 구분하여 엑세스 할수있는 인터넷 전용 소켓 주소 구조체이다.
WSADATA 구조체
typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR *lpVendorInfo;
} WSADATA, *LPWSADATA;
헤더파일 <winsock2.h>
#include "stdafx.h"
#include <winsock2.h> //windows.h보다 먼저 선언해야함
#include <windows.h>
#include <process.h>
#include <stdlib.h>
#include <iostream>
#define BUFSIZE 512
unsigned int WINAPI ServerProc(LPVOID lpParam);
unsigned int WINAPI ClientContorl(LPVOID lpParam);
int main(int argc, char* argv[])
{
DWORD dwID;
HANDLE h = (HANDLE)_beginthreadex(NULL, 0, ServerProc, NULL, 0, (unsigned *)&dwID); //스레드 생성
WaitForSingleObject(h,INFINITE); //스레드 종료를 기다림
printf("Main Thread 종료\n");
CloseHandle(h); //핸들을 반환
return 0;
}
unsigned int WINAPI ServerProc(LPVOID lpParam)
{
WSADATA wsa;
int retval;
//윈속 초기화
/*함수 : int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData );
기능 : WS2_32.DLL의 사용을 초기화한다.
인수 : 버전, WSADATA 구조체의 번지
설명 : 요즘은 보통 Winsock 2.2를 사용하는데, 이렇게 설정하기
위해서 MAKEWORD(2,2)를 사용한다.
반환 : 성공 시 0, 실패 시 에러 코드
주의 : 이 함수는 특별한 경우가 아니면, 한 프로그램에 한 번만 호출하면 된다.*/
if(WSAStartup(MAKEWORD(2,2),&wsa) !=0)
return -1;
/*
함수 : SOCKET socket( int af, int type, int protocol );
기능 : 소켓을 생성한다.
인수 : 1. AF_INET은 TCP/IP, UDP일 경우 사용.
2. SOCK_STREAM(TCP/IP) 또는 SOCK_DGRAM(UDP)
3. IPPROTO_TCP(TCP/IP) 또는 IPPROTO_UDP(UDP), 일반적으로 0 사용.
설명 : 소켓 디스크립터를 생성하고, 필요 자원을 할당한다.
반환 : 성공 시 소켓 디스크립터(descriptor), 실패 시 INVALID_SOCKET
*/
SOCKET listen_sock = socket(AF_INET,SOCK_STREAM,0);
if(listen_sock == INVALID_SOCKET)
printf("소켓 초기화 실패\n");
SOCKADDR_IN serveraddr;
ZeroMemory(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family= AF_INET; //주소체계
serveraddr.sin_port=htons(9000); //포트번호
serveraddr.sin_addr.s_addr=htonl(INADDR_ANY); //네트워크 카드 설정
//bind 서버의 지역 IP주소와 지역 포트번호를 결정
//(클라이언트의 접속을 수용할 소켓,이변수의 주소와 지역포트 번호로 초기화 시킴,
소켓주소 구조체변수의 길이)
/*
클라이언트 프로그램은 필요한 경우만 bind를 사용하면 된다.
함수 : int bind(SOCKET s, const struct sockaddr FAR* name, int namelen );
기능 : 생성된 소켓 s에 네트워크 주소와 포트 번호를 연결한다.
인수 : 1. socket 함수에 의해 생성된 소켓 디스크립터(s)
2. SOCKADDR_IN 구조체. (SOCKADDR*는 struct sockaddr FAR*)
구조체는 주소체계(AF_INET), Port, 네트워크 주소로 채워져야 함.
3. SOCKADDR_IN 구조체의 크기
설명 : 생성된 소켓 s 디스크립터에 포트번호(9999)와 네트워크 주소를 설정.
일반적으로 네트워크 카드는 INADDR_ANY를 사용하는데, INADDR_ANY를 설정하면
운영체제가 자동으로 네트워크 주소를 설정한다. 만약 네트워크 카드가 2개 이상
인 경우, 특정 네트워크 IP를 설정하려면, INADDR_ANY 대신 "220.x.x.x"처럼
직접 설정해야 함.
반환 : 성공 시 0, 실패 시 SOCKET_ERROR
보충 : htons, htonl은 호스트(내 PC)의 바이트 순서를 네트워크 바이트순서로
바꿔주는 함수이다. 이 함수를 사용하지 않고, 그냥 9999를 대입하면 포트번호가
잘못 설정된다.
inet_addr 함수는 네트워크 주소를 4바이트의 IN_ADDR 구조로 바꿔 준다.
*/
retval=bind(listen_sock,(SOCKADDR*)&serveraddr,sizeof(serveraddr));
if(retval==SOCKET_ERROR)
printf("bind error\n");
//listen
//client의 접속을 받아들일수 있는 상태로 포트 상태를 변경한다.
retval=listen(listen_sock,SOMAXCONN);
if(retval==SOCKET_ERROR)
printf("listen error\n");
SOCKET client_sock;
SOCKADDR_IN clientaddr;
int addrlen;
HANDLE hThread;
DWORD THreadID;
//accept()
addrlen = sizeof(clientaddr);
//클라이언트에서 접근을 하면 연결을 허락해준다.
//(소켓 서버, 클라이언트의 주소(sockaddr 타입), 클라이언트 주소의사이즈)
do
{
printf("client 접속대기\n");
client_sock = accept(listen_sock,(SOCKADDR *)&clientaddr,&addrlen);
if(client_sock ==INVALID_SOCKET)
{
printf("accept error\n");
}
Sleep(1);
}while(client_sock==INVALID_SOCKET);
printf("[TCP 서버]클라이언트 접속: IP 주소=%s, 포트번호 %d\n",\
inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
hThread = (HANDLE)_beginthreadex(NULL, 0, ClientContorl,(LPVOID)client_sock, 0, (unsigned *)&THreadID); //스레드 생성
if(hThread==NULL)
printf("Client Thread Error\n");
WaitForSingleObject(hThread,INFINITE); //스레드 종료를 기다림
printf("server thread 종료\n");
CloseHandle(hThread);
closesocket(listen_sock);
/*
함수 : int closesocket( SOCKET s );
기능 : 소켓을 닫고, 자원을 해제한다.
인수 : 1. 닫을 소켓 디스크립터(s 또는 cs)
설명 : 소켓을 닫는다.
반환 : 성공 시 0, 실패 시 SOCKET_ERROR.
주의 : closesocket 함수 사용 시 SO_LINGER 옵션과 SO_DONTLINGER 옵션의
영향을 받기 때문에 주의하자.아래의 표에 보면,SO_LINGER의 설정 값이 l_onoff
는 0이고, l_linger도 0일 때에는 즉시 닫힘(hard close)이 발생하여 소켓은
즉시 제거되고,대기 중인 송수신 데이터는 모두 잃게 된다.
안전한 데이터 송수신의 종료를 위해서는 shutdown 함수를 사용하는 것이 좋다.
옵션 | 타임아웃간격 닫힘유형 닫힘대기여부 비고
------------------------------------------------------------------------
SO_DONTLINGER | 상관 없음 정상 블록 안됨 데이터 안전 전송
SO_LINGER | 0 hard 블록 안됨 데이터 손실 가능
SO_LINGER | >0 정상 블록 됨 일정시간 데이터 전송
SO_LINGER 옵션은 다음과 같이 설정할 수 있다. 이렇게 설정하면 closesocket 함수
사용 시 60초간 대기하면서 큐에 있는 데이터를 전송한다. 만약 전송이 완료되면,
60초가 되기 전에 블록이 해제된다. 중요한 데이터를 송신 중일 때는 이 방법을
사용하는 것이 좋다. 물론 closesocket 함수는 기본적으로 SO_DONTLINGER 옵션이
있기 때문에 이 방법을 사용하지 않아도 된다.
LINGER linger = { 1, 60 }; // 1(기능 사용), 종료 시 60 초간 대기 설정
if( setsockopt( s, SOL_SOCKET, SO_LINGER, (char*)&linger,sizeof
(linger) ) != 0 )
{
printf( "종료 설정 실패, 에러코드 = %d \n", WSAGetLastError() );
closesocket( s ); // 소켓 제거
WSACleanup(); // WS2_32.DLL 사용 종료
return;
}
*/
WSACleanup(); //윈속 종료
/*
함수 : int WSACleanup( void );
기능 : WS2_32.DLL의 사용을 종료한다.
인수 : 1. 닫을 소켓 디스크립터(s 또는 cs)
설명 : WS2_32.DLL의 사용을 종료한다.
반환 : 성공 시 0, 실패 시 SOCKET_ERROR.
주의 : 프로그램이 닫혀지기 전에 한 번만 호출하면 된다.
만약 프로그램이 실행 중에 이 함수를 호출한다면 모든 소켓은 종료된다.
*/
return 0;
}
unsigned int WINAPI ClientContorl(LPVOID lpParam)
//클라이언트 접속시 데이타 처리부분
{
return 0;
}
'코스웨어 > 10년 시스템제어' 카테고리의 다른 글
13번 배정훈 보고서(4월 9일) (1) | 2010.04.11 |
---|---|
12번 박철민 보고서. (1) | 2010.04.08 |
11번 박동원 Atmega128 (1) | 2010.04.08 |
11번 박동원 네트워크 (1) | 2010.04.08 |
수업 사진 20100322 (5) | 2010.04.06 |
시스템제어 - 4월2일 보고서- 8번 남민호 (1) | 2010.04.04 |
시스템제어 - 4/1 - 7번 김진웅 보고서입니다. (4) | 2010.04.01 |
3 / 31 보 고 서 (연결 리스트1) - 6번 김신호 (2) | 2010.03.31 |