-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.c
145 lines (130 loc) · 2.37 KB
/
client.c
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
#include "client.h"
#include <string.h>
#include <stdio.h>
#include <winsock2.h>
static int
receive_all
(
SOCKET sock,
char * buf,
int len
)
{
int received = 0;
int rv;
recv_again:
rv = recv(sock, buf, len, 0);
if ( rv != SOCKET_ERROR )
{
received += rv;
if ( received < len )
goto recv_again;
else
return 1;
}
else
return 0;
}
enum Phase {
phase_get_nickname_length,
phase_get_nickname,
phase_get_message_length,
phase_get_message
};
DWORD WINAPI
receive_thread
(
LPVOID data
)
{
SOCKET sock = *(SOCKET *)data;
enum Phase phase = phase_get_nickname_length;
unsigned char nickname_length = 0;
char nickname[32];
unsigned char message_length = 0;
char message[256];
FILE * log_file = fopen("log.txt", "a");
for ( ; ; )
{
switch ( phase )
{
case phase_get_nickname_length:
if ( recv(sock, &nickname_length, 1, 0) )
{
phase = phase_get_nickname;
break;
}
else
return 0;
case phase_get_nickname:
if ( receive_all(sock, nickname, nickname_length) )
{
phase = phase_get_message_length;
break;
}
else
goto exit_point;
case phase_get_message_length:
if ( recv(sock, &message_length, 1, 0) )
{
phase = phase_get_message;
break;
}
else
goto exit_point;
case phase_get_message:
if ( receive_all(sock, message, message_length) )
{
printf("%.*s wrote: %.*s\n", nickname_length, nickname, message_length, message);
if ( log_file ){
fprintf(log_file, "%.*s wrote: %.*s\n", nickname_length, nickname, message_length, message);
fflush(log_file);
}
phase = phase_get_nickname_length;
break;
}
else
goto exit_point;
}
}
exit_point:
if ( log_file )
fclose(log_file);
return 0;
}
int client
(
SOCKET sock
)
{
int rv;
HANDLE thread_handle;
if ( thread_handle = CreateThread(NULL, 0, receive_thread, &sock, 0, NULL) )
{
for ( ; ; )
{
char message[256];
puts("Enter a message:");
fgets(message+1, sizeof(message)-1, stdin);
if ( message[1] == '\n' )
break;
else
{
size_t msg_len = strlen(message+1);
message[msg_len] = 0;
*message = msg_len-1;
send(sock, message, msg_len, 0);
}
}
rv = 1;
}
else
rv = 0;
closesocket(sock);
if ( thread_handle )
{
WaitForSingleObject(thread_handle, INFINITE);
CloseHandle(thread_handle);
}
return rv;
}