본문 바로가기

전공 과목 시험정리/C 프로그래밍

Fate 서버 소스 (미완성)

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 <-- 뮤텍스, 세마포어에 관한 정리.

대기열(큐) 같은 개념