-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathweek_14_2_server.cpp
More file actions
163 lines (128 loc) · 4.14 KB
/
week_14_2_server.cpp
File metadata and controls
163 lines (128 loc) · 4.14 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
/*
* NCYU 109 Network Programming
* Chat room server multiple thread server
* Created by linwebs on 2021/5/24.
*/
#include <iostream>
#include <winsock.h>
#define MAX_CLIENT 2
using namespace std;
void *thread_main(void *thread_arg);
/**
* structure of arguments to pass to client thread
*/
struct thread_args {
int client_sock[MAX_CLIENT]; // socket descriptor for client
};
int main() {
int thread_id; // thread_id from CreateThread()
thread_args *thread_arg; // pointer to argument structure for thread
int server_sock; // socket descriptor for server
int client_sock[MAX_CLIENT]; // socket descriptor for client
WSADATA wsadata; // structure for WinSock setup communication
sockaddr_in server_addr{}; // local address
sockaddr_in client_addr{}; // client address
int client_length; // length of client address data structure
// load Winsock 2.0 DLL
if (WSAStartup(0x101, &wsadata) != 0) {
cout << "WSAStartup() failed" << endl;
exit(1);
}
// create socket for incoming connections
if ((server_sock = int(socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) < 0) {
cout << "socket() failed" << endl;
}
// construct local address structure
memset(&server_addr, 0, sizeof(server_addr)); // zero out structure
server_addr.sin_family = AF_INET; // internet address family
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // any incoming interface
server_addr.sin_port = htons(5678); // local port
// bind to the local address
if (bind(server_sock, (struct sockaddr *) &server_addr, sizeof server_addr) < 0) {
cout << "bind() failed" << endl;
}
// mark the socket so it will listen for incoming connections
if (listen(server_sock, 3) < 0) {
cout << "listen() failed" << endl;
}
while (true) {
cout << "Server is waiting for clients." << endl;
client_length = sizeof(client_addr);
// wait for a client to connect
for (int i = 0; i < MAX_CLIENT; i++) {
if ((client_sock[i] = int(accept(server_sock, (struct sockaddr *) &client_addr, &client_length))) <= 0) {
cout << "accept() failed" << endl;
} else {
cout << "accept [" << i << "]" << endl;
}
}
// create separate memory for client argument
thread_arg = new thread_args;
for (int i = 0; i < MAX_CLIENT; i++) {
thread_arg->client_sock[i] = client_sock[i];
}
if (CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE) thread_main, thread_arg, 0, (LPDWORD) &thread_id) ==
nullptr) {
cout << "thread_create() failed" << endl;
//break;
}
cout << "New chat room with thread ID: " << thread_id;
for (int i = 0; i < MAX_CLIENT; i++) {
cout << " and ";
if (i == 0) {
cout << "sockets: ";
}
cout << thread_arg->client_sock[i];
}
cout << endl;
}
return 0;
}
/**
* Main program of a thread
* @param thread_arg
* @return
*/
void *thread_main(void *thread_arg) {
int client_sock[MAX_CLIENT]; // socket descriptor for client connection
// extract socket file descriptor from argument
for (int i = 0; i < MAX_CLIENT; i++) {
client_sock[i] = ((struct thread_args *) thread_arg)->client_sock[i];
}
char buffer[1000]; // buffer for echo string
int recv_msg_size; // size of received message
u_long mode = 1;
// set non blocking
for (int i = 0; i < MAX_CLIENT; i++) {
ioctlsocket(client_sock[i], FIONBIO, &mode);
}
int wsa_error;
bool exit_loop = false;
// send received string and receive again until end of transmission
while (true) {
for (int i = 0; i < MAX_CLIENT; i++) {
if ((recv_msg_size = recv(client_sock[i], buffer, 1000, 0)) > 0) {
for (int j = 0; j < MAX_CLIENT; j++) {
if (j != i) {
send(client_sock[j], buffer, int(strlen(buffer) + 1), 0);
}
}
}
wsa_error = WSAGetLastError();
if (wsa_error != WSAEWOULDBLOCK && wsa_error != 0) {
cout << "Disconnected! error code: " << wsa_error << endl;
exit_loop = true;
break;
}
}
if (exit_loop) {
break;
}
Sleep(1000);
}
for (int i = 0; i < MAX_CLIENT; i++) {
closesocket(client_sock[i]); // close client socket
}
free(thread_arg);
return nullptr;
}