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 152 153 154 155 156 157 | #include <stdio.h> #include <string.h> #include <winsock.h> #include <process.h> #pragma comment(lib,"wsock32.lib") #define PORT 5000 // 사용할 포트는 5000 #define IP "127.0.0.1" // 접속할 서버는 로컬 호스트 void recv_thread(void*); // 스레드 수행 함수의 프로토 타입 int socket_make(); int message_send(char get[]); int ret = 0; // 리턴 값 int s = 0; // 소켓 값 HANDLE hMutex; // 뮤텍스용 int message_send(char get[]){ send(s,get,strlen(get),0); return 0; } int main() { socket_make(); message_send("testing"); Sleep(1000000000000); } // 받는 스레드 부분 void recv_thread(void* pData) { int ret_thread = 65535; char buff_thread[1024] = {0}; // 스레드용 리턴 값이 우너하는 값이 아니면 받는 중에 서버와 통신이 끊겼다고 보고 나감 while(ret_thread != INVALID_SOCKET || ret_thread != SOCKET_ERROR) { Sleep(10); // CPU 점유률 100% 방지용 // 서버에서 주는 메시지를 실시간으로 기다렸다가 받습니다. ret_thread = recv(s, buff_thread, sizeof(buff_thread), 0); // 서버에서 받는 작업을 한 결과 비정상일 때 탈출 if(ret_thread == INVALID_SOCKET || ret_thread == SOCKET_ERROR) break; // 정상적으로 받은 버퍼를 출력 /* 메세지가 buff_thread 라는 배열에 담긴 상태임 */ printf("\n%d 메시지 받음 : %s", strlen(buff_thread), buff_thread); memset(buff_thread,0,1024); // 받은 버퍼를 초기와 } // 작업이 끝난 소켓을 무효화시킴 WaitForSingleObject(hMutex,100L); ret = INVALID_SOCKET; ReleaseMutex(hMutex); return; } int socket_make(){ // 뮤택스 초기화 hMutex = CreateMutex(NULL, FALSE, FALSE); if(!hMutex) { printf("Mutex 생성 오류\n"); return 1; } // 윈속 초기화 WSADATA wsd; char buff[1024]; if(WSAStartup(MAKEWORD(2,2), &wsd) != 0) { printf("Winsock 오류\n"); return 1; } // 서버로 접속하기 위한 소켓 생성 sockaddr_in server; s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (s == SOCKET_ERROR) { printf("socket() 오류\n"); closesocket(s); WSACleanup(); return 1; } server.sin_addr.s_addr = inet_addr(IP); server.sin_family = AF_INET; server.sin_port = htons(PORT); // 서버와 연결 if( connect(s, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) { printf("connect() 오류\n"); closesocket(s); WSACleanup(); return 1; } printf("서버와 연결이 되었음.\n"); // 서버에서 우선 주는 Welcome 메시지 분석 ret = recv(s, buff, 1024,0); printf("%s", buff); // 가득 찼다고 메시지가 왔다면 if(!strcmp("FULL.\n",buff)) { closesocket(s); WSACleanup(); return 0; // 접속을 종료 } // 정상 접속이 되면 스레드 작동 - 받는 메시지를 스레드로 실시간 수행 _beginthread(recv_thread, 0, NULL); /* while(ret != INVALID_SOCKET || ret != SOCKET_ERROR) { // 딜레이 : CPU 점유율 감소용 Sleep(10); printf("보낼 메시지 입력 : "); fgets(buff, 1024, stdin); // 전송 결과 잘못 된 결과를 얻었을때 탈출 if(ret == INVALID_SOCKET || ret == SOCKET_ERROR) break; // 서버로 보내는 글은 fgets 을 받고 나서 순차적으로 보냄 ret = send(s, buff, strlen(buff), 0); // 버퍼 초기화 memset(buff, 0, 1024); } */ return 0; } | cs |
친구랑 같이 만들던 FATE 라는 게임의 서버 소스였는데, 리눅스에서 가상머신으로 윈도우 소켓을 개발하다가 완성본 소스가 날라가 버려서 미완성의 소스 밖에 없다.
원래 리눅스 기반에서 개발하는 것을 좋아하는데, 윈도우에서 돌아가는 프로그램을 작성하려니 여러 블로그에서 소스를 막 가져오게 되었다.
결과적으로 프로그램이 많이 더러워 졌는데, 그 당시에 Extending 과 Embedding 을 알았더라면 하는 아쉬움이 있다.
Extending : Python 에서 C 모듈을 사용하는 것.
Embedding : C 에서 Python 모듈을 사용하는 것.물론 지금도 확실하게 아는 건 아니지만, 그 친구는 윈도우 C++ 만 하는 친구라 나와 플랫폼이나 언어도 맞지 않아서 그 당시에 결국 구현에 실패했던게 너무 아쉬웠다.
--------------------------------------------------------------
당시에 발생했던 오류는 "중복 선언" 이었는데, windows.h 와 winsock2.h 에서 socket() 에 대한 중복선언이 되어 있다고 한다.
그래서 #pragma 를 이용해 windows.h 에서의 socket() 선언을 제외해주면 에러가 발생하지 않는다.
http://topnanis.tistory.com/195 <-- 뮤텍스, 세마포어에 관한 정리.
대기열(큐) 같은 개념
'전공 과목 시험정리 > C 프로그래밍' 카테고리의 다른 글
C와 C++ 동시사용 (0) | 2015.05.10 |
---|---|
C++ 에서의 소켓프로그래밍 (0) | 2015.04.25 |
fork 로 프로세스 생성 후, 프로세스간 변수 공유 (0) | 2015.04.25 |
웹에서 서버정보 파싱 (0) | 2015.04.25 |
쓰레드 프로그램 (0) | 2015.04.25 |