-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathservice.c
More file actions
195 lines (160 loc) · 5.87 KB
/
service.c
File metadata and controls
195 lines (160 loc) · 5.87 KB
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<pthread.h>
#include<Windows.h>
#include"GoBangAI.h"
#define MAX_CONNECT 100
#define Length 15
#define BUF_SIZE 1024
#pragma comment(lib,"pthreadVC2.lib")
#pragma comment(lib,"ws2_32.lib")
typedef struct Player_Data Player_Data;
struct Player_Data
{
int PlayerID;
SOCKET client_socket;
struct sockaddr_in client_Info;
};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int playerct = 1;
// 這裡開始執行client的thread
void* Client_Process(void* client_data)
{
struct chess_data
{
int x_axis;
int y_axis;
};
struct chess_data chess_data;
Player_Data* data = (Player_Data*)client_data;
int err_tag;
int recv_len = 0;
char recv_buf[BUF_SIZE] = ""; // 接收緩衝區
char snd_buf[BUF_SIZE]; //輸出緩存區
int CheckerBoard[Length][Length];
for (int i = 0; i < Length; i++) //初始化棋盘
for (int j = 0; j < Length; j++)
CheckerBoard[i][j] = 2;
CheckerBoard[7][7] = 0; //AI第一手必下天元
SOCKET socket = data->client_socket; //接收傳過來的socket
struct sockaddr_in client_Info = data->client_Info; //接收傳過來的client資料
int ID = data->PlayerID; // 接收playerID
printf("player%d 連入伺服器 port:%d\n", ID, client_Info.sin_port);
// 解鎖,pthread_mutex_lock()喚醒,不阻塞
pthread_mutex_unlock(&mutex);
// 接收數據
err_tag = recv(socket, recv_buf, 1024, 0);
printf("客戶端%d發來資料:%s\n", ID, recv_buf);
// 開始循環接收client端傳來的落子位置,并返回AI的選擇
while (1)
{
memset(recv_buf, 0, 1024);
err_tag = recv(socket, recv_buf, 1024, 0);
if (err_tag > 0)
{
memcpy(&chess_data, recv_buf, sizeof(chess_data));//將接受到的信息轉換為struct結構
CheckerBoard[chess_data.x_axis][chess_data.y_axis] = 1;//將client端的落子信息輸入到棋盤
//printf("player%d data1:%d data2:%d\n", ID, chess_data.x_axis, chess_data.y_axis);
chess_t s;
chess_t* chess = &s;
chess->x = 0;
chess->y = 0;
//AI選擇落子位置
Chess_AI(chess, CheckerBoard);
//將AI的落子位置傳給client端
//printf("server reply: data1:%d data2:%d\n", chess->x, chess->y);
chess_data.x_axis = chess->x;
chess_data.y_axis = chess->y;
CheckerBoard[chess_data.x_axis][chess_data.y_axis] = 0; // 將棋盤中的相應位置設為黑棋
memset(snd_buf, 0, BUF_SIZE);//清空緩存
memcpy(snd_buf, (void*)&chess_data, sizeof(chess_data));
send(socket, snd_buf, sizeof(snd_buf), 0);
}
else if (err_tag == 0)
{
//當ret == 0 說明客戶端已斷開連線。這裡我們直接跳出迴圈去等待下次連線即可。
printf("客戶端斷開連線, ID = %d PORT = %d \n", ID, client_Info.sin_port);
playerct = playerct - 1;
closesocket(socket);
break;
}
else
{
//當err_tag < 0 說明出現了異常 例如阻塞狀態解除,或者讀取資料時出現指標錯誤等。
//所以我們這裡要主動斷開和客戶端的連結,然後跳出迴圈去等待新的連線。
printf("在與客戶端通訊是發生異常 ID = %d PORT = %d \n", ID, client_Info.sin_port);
playerct = playerct - 1;
closesocket(socket);
break;
}
}
printf("player %d disconnect! PORT:%d\n", ID, client_Info.sin_port);
return NULL;
}
int main(int argc, char* argv[])
{
static SOCKET server_socket;
static struct sockaddr_in server_Info; //儲存socket資訊
int client_count = 0;
int port = 6666; // 設置port號
WORD socket_version = MAKEWORD(2, 2);
WSADATA wsadata;
if (WSAStartup(socket_version, &wsadata) != 0)
{
return 0;
}
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//建立socket 並判斷是否建立成功
if (server_socket == INVALID_SOCKET)
{
printf("socket error\n");
return 0;
}
server_Info.sin_family = AF_INET;
server_Info.sin_port = htons(port);
server_Info.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(server_socket, (LPSOCKADDR)&server_Info, sizeof(server_Info)) == SOCKET_ERROR)
{
printf("bind error\n");
}
if (listen(server_socket, 5) == SOCKET_ERROR)
{
printf("listen error\n");
return 0;
}
printf("成功啟動server PORT:%d 正在等待連接....\n", port);
char inputBuffer[256] = {};
char message[] = { "Hi,this is server.\n" };
int connfd = 0;
while (1)
{
SOCKET client_socket;
struct sockaddr_in client_Info;
int client_Info_len;
client_Info_len = sizeof(client_Info);
// 鎖住,不讓多個client同時連接server
pthread_mutex_lock(&mutex);
client_socket = accept(server_socket, (SOCKADDR*)&client_Info, &client_Info_len);
if (client_socket == INVALID_SOCKET)
{
printf("accept error\n");
continue; //繼續等待下一次連線
}
else
{
Player_Data data; // 建立player的資訊結構
data.PlayerID = playerct;
data.client_socket = client_socket;
memcpy(&(data.client_Info), &client_Info, sizeof(client_count));
printf("player %d has has connected\n", playerct);
printf("-----------------------------\n");
playerct = playerct + 1;
pthread_t thread_id;
pthread_create(&thread_id, NULL, Client_Process, (void*)&data); // 建立thread
pthread_detach(thread_id);
}
}
closesocket(server_socket);
return 0;
}