티스토리 뷰
02_network_testeventsample.zip
스레드
하나의 프로세스에서 다중 작업이 동시에 하는 것
스레드 관련 함수
--------------------------------------------------------
HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in_opt LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out_opt LPDWORD lpThreadId
);
lpThreadAttributes - 스레드에 대한 보안 속성 구조체 포인터
dwStackSize - 스레드에서 사용할 스택 사이즈, 0이면 시스템에서 사용하는 기본 사이즈를 제공한다.
lpStartAddress - 스레드 구동 함수 포인터 typedef DWORD (WINAPI* LPTHREAD_START_ROUTINE)(LPVOID)
lpParameter - 스레드 구동 함수에 넘길 파라메터
dwCreateFlags - 값이 0이면 스레드가 만들어지자마자 구동되며, CREATE_SUSPENDED 값으로 지정되면, ResumeThread() 함수를 통해 스레드 구동을 할 수 있다.
lpThreadId - 스레드 ID값
Return Value
스레드 핸들
--------------------------------------------------------
DWORD WINAPI WaitForSingleObject(
__in HANDLE hHandle,
__in DWORD dwMilliseconds
);
hHandle - 핸들
dwMilliseconds - 타임아웃 대기시간, 밀리세컨 단위
Return Value
WAIT_ABANDONED
WAIT_OBJECT_0 - 핸들의 시그널 값 확인
WAIT_TIMEOUT - 타임아웃
-------------------------------------------------------
[예제 코드 - 이벤트 확인]
#include <windows.h>
DWORD WINAPI TickThreadProc(LPVOID lpParam)
{
HANDLE hEvent = (*(HANDLE*)lpParam);
while(1)
{
Sleep(1000);
SetEvent(hEvent);
ResetEvent(hEvent);
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD dwThread_ID;
HANDLE hThread = CreateThread(NULL, 0, TickThreadProc, (LPVOID)&hEvent, 0, &dwThread_ID);
while(1)
{
if(WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0)
printf("틱 떳다\n");
}
}
[예제 코드 - 클라이언트]
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX_BUFFER_SIZE 512
void err_quit(char* msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR);
LocalFree(lpMsgBuf);
exit(-1);
}
void err_display(char* msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
printf("[%s] %s", msg, (LPCTSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}
DWORD WINAPI RecvThreadProc(LPVOID pParam)
{
SOCKET sock = (*(SOCKET*)pParam);
char recvBuffer[MAX_BUFFER_SIZE + 1];
int readByte;
while(1)
{
readByte = recv(sock, recvBuffer, MAX_BUFFER_SIZE, 0);
if(readByte == SOCKET_ERROR)
{
err_display("recv()");
break;
}
else if(readByte == 0)
{
break;
}
else
{
recvBuffer[readByte] = '\0';
printf("서버 수신 데이터 :[%d Byte] %s\n", readByte, recvBuffer);
recvBuffer[0] = '\0';
}
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsa;
if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
return -1;
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if(clientSocket == INVALID_SOCKET)
err_quit("socket()");
SOCKADDR_IN serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(5001);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
int retValue = connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if(retValue == SOCKET_ERROR)
err_quit("connect()");
// 스레드 생성
DWORD dwThread_ID;
HANDLE hRecvThread = CreateThread(NULL, 0, RecvThreadProc, (LPVOID)&clientSocket, 0, &dwThread_ID);
char writeBuffer[MAX_BUFFER_SIZE + 1];
DWORD ret;
while(1)
{
printf("서버에 보낼 데이터 : ");
scanf_s("%s", &writeBuffer, MAX_BUFFER_SIZE);
ret = WaitForSingleObject(hRecvThread, 100); // 스레드 상태 확인
if(ret == WAIT_OBJECT_0) // 만약 스레드가 종료되었다면
{
printf("\n서버와의 접속이 끊어졌습니다.\n");
break;
}
send(clientSocket, writeBuffer, strlen(writeBuffer), 0); // 입력한 데이터를 보낸다.
}
return 0;
}
[예제코드 - 서버]
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX_BUFFER_SIZE 512
void err_quit(char* msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR);
LocalFree(lpMsgBuf);
exit(-1);
}
void err_display(char* msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
printf("[%s] %s", msg, (LPCTSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}
DWORD WINAPI RecvThreadProc(LPVOID pParam)
{
SOCKET sock = (*(SOCKET*)pParam);
int retValue;
char recvBuffer[MAX_BUFFER_SIZE + 1];
while(1)
{
retValue = recv(sock, recvBuffer, MAX_BUFFER_SIZE, 0);
if(retValue == SOCKET_ERROR)
{
err_display("recv()");
break;
}
else if(retValue == 0)
{
break;
}
else
{
recvBuffer[retValue] = '\0';
printf("%d %s\n", sock, recvBuffer);
send(sock, recvBuffer, strlen(recvBuffer), 0);
}
}
closesocket(sock);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsa;
if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
return -1;
SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, 0);
if(listenSocket == INVALID_SOCKET)
err_quit("socket()");
SOCKADDR_IN serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(5001);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
int retValue = bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if(retValue == SOCKET_ERROR)
err_quit("bind()");
retValue = listen(listenSocket, SOMAXCONN);
if(retValue == SOCKET_ERROR)
err_quit("listen()");
SOCKET clientSocket;
SOCKADDR_IN clientAddr;
int nAddrLength;
while(1)
{
nAddrLength = sizeof(clientAddr);
clientSocket = accept(listenSocket, (SOCKADDR*)&clientAddr, &nAddrLength);
if(clientSocket == INVALID_SOCKET)
{
err_display("accept()");
continue;
}
printf("\n[TCP 서버] 클라이언트 접속 : 소켓번호 = %d, IP 주소 = %s, 포트번호 = %d\n",
clientSocket, inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
DWORD dwThread_ID;
HANDLE hClientThread = CreateThread(NULL, 0, RecvThreadProc, (LPVOID)&clientSocket, 0, &dwThread_ID);
}
closesocket(listenSocket);
WSACleanup();
return 0;
}
[출처] 스레드란 (정문수 개인 카페) |작성자 유빈아빠
'Programming > Network' 카테고리의 다른 글
소켓의 입출력 모델 준비 (0) | 2011.03.08 |
---|---|
Socket Option (소켓 옵션 세팅) (0) | 2011.03.08 |
소켓이란? NetWork에 대한 첫걸음 (0) | 2011.03.08 |
네트워크 란? (0) | 2011.03.08 |