1. 서버
-Serv.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | #include <iostream> #include <stdio.h> #include <functional> #include <WinSock2.h> #include <queue> #include <process.h> #define PORT 5000 typedef struct _cliInfo{ char * msg; struct sockaddr_in clientAddr; }cliInfo; using namespace std; class Serv{ public : WORD wVersionRequested; //WORD is a 16-bit unsigned interger. 0000(low-order word)0000(high-order word) WSADATA wsaData; SOCKET sd; struct sockaddr_in serverAddr; // clientAddr; char * serverIP; struct hostent *host; char host_name[BUFSIZ]; int sockAddrLen; queue<cliInfo*> q; function< void (Serv*)> userFunc; HANDLE msgMutex; HANDLE processingEvent; HANDLE receiveThread; DWORD receiveThreadID; HANDLE processThread; DWORD processThreadID; Serv(); ~Serv(); int bindServerSocket(); static unsigned int WINAPI receive( void * serv); static unsigned int WINAPI process( void * serv); int startThread(); }; |
-Serv.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | #include "Serv.h" using namespace std; int Serv::bindServerSocket(){ //UDP형식의 소켓 생성 //The Internet Protocol version 4 (IPv4) address family. //PF: protocol family sd = socket(AF_INET, SOCK_DGRAM, 0); //소켓 생성 오류 처리 if (sd == INVALID_SOCKET) { fprintf (stderr, "Could not create socket.\n" ); WSACleanup(); return 1; } //server setting serverAddr.sin_family=AF_INET; serverAddr.sin_port=htons(PORT); //convert byte order short data type gethostname(host_name, sizeof (host_name)); //getting server IP by hostname host = gethostbyname(host_name); if (host == NULL) { fprintf (stderr, "Could not get host name.\n" ); closesocket(sd); WSACleanup(); return 1; } memcpy (&serverAddr.sin_addr, host->h_addr_list[0], host->h_length); //서버 ip 설정 //Bind address to socket ::bind(sd, ( struct sockaddr *)&serverAddr, sizeof ( struct sockaddr_in)); if (sd==NULL ) { fprintf (stderr, "Could not bind name to socket.\n" ); closesocket(sd); WSACleanup(); return 1; } // Print out server information serverIP=inet_ntoa(serverAddr.sin_addr); printf ( "Server running on %s\n" ,serverIP); return 0; }; unsigned int Serv::receive( void * serv) { char * msg; struct sockaddr_in clientAddr; cliInfo* cli; Serv* server=(Serv*)serv; int n; char * clientIP; //get messages from client and put it in the Queue do { msg=( char *) malloc ( sizeof ( char )*BUFSIZ); cli=(cliInfo*) malloc ( sizeof (cliInfo)); memset (( void *)cli, '\0' , sizeof (cliInfo)); //server->sockAddrLen=sizeof(server->clientAddr); n=recvfrom(server->sd,msg,BUFSIZ,0,( struct sockaddr *)&(clientAddr),&(server->sockAddrLen)); msg[n]= '\0' ; clientIP=inet_ntoa(clientAddr.sin_addr); cli->clientAddr=clientAddr; cli->msg=msg; if (n!=0){ printf ( "gotten messege from %s\n" , clientIP ); printf ( "message: %s\n" , cli->msg ); } //mutex lock befor using Queue WaitForSingleObject(server->msgMutex,INFINITE); __try { server->q.push(cli); } __finally { //mutex unlock ReleaseMutex(server->msgMutex); } //set the event signaled after putting msg into the queue SetEvent(server->processingEvent); } while ( strcmp (msg, "quitserver" )!=0); return 0; } //큐에 있는 메세지를 user defined funtion으로 처리 unsigned int Serv::process( void * serv){ Serv* server=(Serv*)serv; //WaitForSingleObject(server->receiveThread,INFINITE); //while(WaitForSingleObject(server->receiveThread,INFINITE)==WAIT_OBJECT_0){ while (1){ //event가 signaled 상태가 될때까지 기다림 WaitForSingleObject(server->processingEvent,INFINITE); //event가 signaled 상태가 된 후 user defined funtion실행 server->userFunc(server); //메세지 큐가 비어있으면 event를 nonsignaled 상태로 바꿔줌 if (server->q.empty()) ResetEvent(server->processingEvent); } return 0; } //thread를 실행 int Serv::startThread(){ receiveThread=( HANDLE )_beginthreadex(NULL,0,Serv::receive,( void *) this ,0,(unsigned*)&receiveThreadID); processThread=( HANDLE )_beginthreadex(NULL,0,Serv::process,( void *) this ,0,(unsigned*)&processThreadID); return 0; } Serv::Serv() { wVersionRequested=MAKEWORD(2,2); //window soket 요구 최저버전 WSAStartup(0x0101, &wsaData); msgMutex=CreateMutex(NULL,FALSE,NULL); processingEvent = CreateEvent( NULL, // default security attributes TRUE, // manual-reset event FALSE, // initial state is nonsignaled TEXT( "ProcessingEvent" ) // object name ); sockAddrLen= sizeof (sockaddr_in); } Serv::~Serv() { closesocket(sd); WSACleanup(); } |
-main.cpp(Server)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | #include <iostream> #include <stdio.h> #include <functional> #include <WinSock2.h> #include <queue> #include <process.h> #define PORT 5000 typedef struct _cliInfo{ char * msg; struct sockaddr_in clientAddr; }cliInfo; using namespace std; class Serv{ public : WORD wVersionRequested; //WORD is a 16-bit unsigned interger. 0000(low-order word)0000(high-order word) WSADATA wsaData; SOCKET sd; struct sockaddr_in serverAddr; // clientAddr; char * serverIP; struct hostent *host; char host_name[BUFSIZ]; int sockAddrLen; queue<cliInfo*> q; function< void (Serv*)> userFunc; HANDLE msgMutex; HANDLE processingEvent; HANDLE receiveThread; DWORD receiveThreadID; HANDLE processThread; DWORD processThreadID; Serv(); ~Serv(); int bindServerSocket(); static unsigned int WINAPI receive( void * serv); static unsigned int WINAPI process( void * serv); int startThread(); }; |
2. 클라이언트
-main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | #include <iostream> #include <WinSock2.h> #include <stdio.h> #include <string> #define PORT 5000 #pragma comment(lib, "Ws2_32.lib") int main(){ SOCKET sd; struct sockaddr_in serverAddr, clientAddr; char sendline[BUFSIZ]; char recvline[BUFSIZ]; char tmp[BUFSIZ]; char serverIP[BUFSIZ]; int n,serversize; WSADATA w; int check; if (WSAStartup(0x0101, &w) != 0) { fprintf (stderr, "Could not open Windows connection.\n" ); exit (0); } printf ( "inputIPaddr: " ); scanf_s( "%s" ,serverIP, sizeof (serverIP)); sd=socket(AF_INET, SOCK_DGRAM, 0); memset (( void *)&serverAddr, '\0' , sizeof ( struct sockaddr_in)); serverAddr.sin_family=AF_INET; serverAddr.sin_addr.s_addr=inet_addr(serverIP); serverAddr.sin_port=htons(PORT); memset (( void *)&clientAddr, '\0' , sizeof ( struct sockaddr_in)); /* Set family and port */ clientAddr.sin_family = AF_INET; clientAddr.sin_addr.s_addr=INADDR_ANY; clientAddr.sin_port = htons(0); if (bind(sd, ( struct sockaddr *)&clientAddr, sizeof ( struct sockaddr_in)) == -1) { printf ( "CreateSocket failed (%d)\n" , GetLastError()); closesocket(sd); WSACleanup(); exit (0); } while (1){ printf ( "input anymessage: " ); scanf ( "%s" ,tmp, BUFSIZ); strcpy (sendline,tmp); if (! strcmp (sendline, "q" )) break ; check=sendto(sd,sendline, strlen (sendline),0,( struct sockaddr*)&serverAddr, sizeof (serverAddr)); if (check==-1) break ; serversize= sizeof (serverAddr); n=recvfrom(sd,recvline,BUFSIZ,0,( struct sockaddr*)&serverAddr,&serversize); recvline[n]= '\0' ; printf ( "receiveFormServer:" ); fputs (recvline,stdout); printf ( "\n" ); } closesocket(sd); return 0; } |
mutex를 걸어주는 방법에는 critical section (함수?) 도 있다고 한다.....
EVENT 생성시 마지막 인자로 들어가는 TEXT는 안주는 것이 좋다.
EVENT TEXT가 같으면 다른 프로그램에서도 같은 EVENT로 인식을 하기 때문에
-thread 종료를 시키는 방법
thread들은 while문을 돌때 조건으로 flag check를 한다.
delete(소멸자에서) 할때 flag set을 한뒤 waitEvent
thread에서 set된 flag를 확인하고 while문을 빠져나온다.
while문을 빠져나와 thread를 빠져 나오기전 setEvent를 해주면 이벤트를 기다리던 delete함수가 메모리 해제를 시작한다.
'Programming Language > C++' 카테고리의 다른 글
Why do we need virtual functions in c++? (0) | 2019.04.05 |
---|---|
생성자 뒤에 콜론(:) (0) | 2017.03.08 |
MultiThread Programming (0) | 2016.08.17 |