1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+ #include <sys/types.h>
5
+ #include <sys/socket.h>
6
+ #include <arpa/inet.h>
7
+ #include <fcntl.h>
8
+ #include <netdb.h>
9
+ #include <unistd.h>
10
+
11
+ #define PORTNUM 1500 // Port > 1024 because program will not work not as root.
12
+
13
+ // Task:
14
+ // Create a TCP-server which returns astrological forecasts as a response to client command HOROSCOPE.
15
+ // It should remember forecast on a STARS SAY command from client. Server should handle possible errors.
16
+
17
+ // Function read number of bytes and return it. It is necessary to use such a function for read,
18
+ // because system call recv may return not full response and it will be necessary to read in loop.
19
+ ssize_t receive_all (int fd , char * buf , size_t len )
20
+ {
21
+ size_t pos = 0 ;
22
+
23
+ while (pos < len )
24
+ {
25
+ // Buffer returned by system call recv - is not the string, so we can't use string functions with it.
26
+ ssize_t received = recv (fd , buf + pos , len - pos , MSG_NOSIGNAL ); // Receive byte by byte.
27
+
28
+ if (received == -1 ) return -1 ;
29
+ else if (received == 0 ) return pos ;
30
+ else if (received > 0 ) pos += received ;
31
+ }
32
+
33
+ return pos ;
34
+ }
35
+
36
+ void main ()
37
+ {
38
+ printf ("ASTRO Server PID -- %d.\n" , getpid ());
39
+
40
+ // Create socket
41
+ int sockfd = -1 ;
42
+ if ((sockfd = socket (AF_INET , SOCK_STREAM , IPPROTO_TCP )) == -1 )
43
+ {
44
+ perror ("Error of calling socket" ); /* or strerror */
45
+ exit (1 );
46
+ }
47
+
48
+ // For UDP SO_REUSEADDR may mean some problems...
49
+ int optval = 1 ;
50
+ if (setsockopt (sockfd , SOL_SOCKET , SO_REUSEADDR , & optval , sizeof (int )) == -1 )
51
+ {
52
+ perror ("Error of calling setsockopt" );
53
+ exit (1 );
54
+ }
55
+
56
+ // Set address
57
+ struct sockaddr_in serv_addr ;
58
+ memset (& serv_addr , '\0' , sizeof (serv_addr ));
59
+ serv_addr .sin_family = AF_INET ;
60
+ serv_addr .sin_addr .s_addr = htonl (INADDR_ANY ); // 0.0.0.0 (INADDR_LOOPBACK - 127.0.0.1)
61
+
62
+ // Change bytes order to network'
63
+ int nport = htons ((int )PORTNUM );
64
+ serv_addr .sin_port = nport ;
65
+
66
+ // Link socket with address
67
+ if (bind (sockfd , (struct sockaddr * )& serv_addr , sizeof (struct sockaddr )) == -1 )
68
+ {
69
+ perror ("Error of calling bind" );
70
+ exit (1 );
71
+ }
72
+
73
+ fprintf (stderr , "Server is ready: %s\n" , inet_ntoa (serv_addr .sin_addr ));
74
+
75
+ // Server is ready to get SOMAXCONN connection requests (128).
76
+ // This is *SHOULD* be enought to call accept and create child process.
77
+ if (listen (sockfd , SOMAXCONN ) == -1 )
78
+ {
79
+ perror ("Error of calling listen" );
80
+ exit (1 );
81
+ }
82
+
83
+ struct sockaddr_in clnt_addr ;
84
+ socklen_t addrlen = sizeof (clnt_addr );
85
+ memset (& clnt_addr , '\0' , sizeof (clnt_addr ));
86
+
87
+ int newsocket = -1 ;
88
+
89
+ char zodiaks [12 ][12 ] = { "Aries " , "Taurus " , "Gemini " , "Cancer " ,
90
+ "Leo " , "Virgo " , "Libra " , "Scorpio " , "Sagittarius" ,
91
+ "Capricorn " , "Aquarius " , "Pisces " };
92
+
93
+ char descriptions [12 ][80 ] = { "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" };
94
+
95
+ char thanks [] = "THANKS!" ;
96
+ char denied [] = "DENIED!" ;
97
+ char sorry [] = "SORRY!" ;
98
+
99
+ while (1 )
100
+ {
101
+ if ((newsocket = accept (sockfd , (struct sockaddr * )& clnt_addr , & addrlen )) == -1 )
102
+ {
103
+ perror ("Error of calling accept" );
104
+ exit (1 );
105
+ }
106
+
107
+ printf ("Client = %s \n" , inet_ntoa (clnt_addr .sin_addr ));
108
+
109
+ char command [22 ];
110
+ memset (command , '\0' , 22 );
111
+ int received = receive_all (newsocket , command , 22 );
112
+
113
+ printf ("Received from client: %s, %d bytes\n" , command , received );
114
+
115
+ if (received == 22 )// && command[21] == '\n')
116
+ {
117
+ // Get znak zodiak
118
+ char zodiak [11 ];
119
+ for (int i = 10 ; i < 21 ; i ++ )
120
+ {
121
+ zodiak [i - 10 ] = command [i ];
122
+ }
123
+
124
+ printf ("Received from client: zodiak %s\n" , zodiak );
125
+
126
+ // Find it in array.
127
+ int desc_index = -1 ;
128
+ for (int i = 0 ; i < 12 ; i ++ )
129
+ {
130
+ if (strncmp (zodiaks [i ], zodiak , 12 ) == 0 )
131
+ {
132
+ desc_index = i ;
133
+ break ;
134
+ }
135
+ }
136
+
137
+ printf ("Position in array of zodiaks: %d\n" , desc_index );
138
+
139
+ if (strncmp (command , "STARS SAY " , 10 ) == 0 )
140
+ {
141
+ // If found, get description.
142
+ if (desc_index > -1 )
143
+ {
144
+ // Receive 80 bytes of description.
145
+ char desc [80 ];
146
+ memset (desc , '\0' , 80 );
147
+
148
+ int received_dest = receive_all (newsocket , desc , 80 );
149
+
150
+ if (received_dest > 0 )
151
+ {
152
+ memcpy (descriptions [desc_index ], desc , received_dest );
153
+ }
154
+
155
+ printf ("Received from client: %s, %d bytes\n" , desc , received_dest );
156
+
157
+ // Send thanks
158
+ int sent = send (newsocket , thanks , strlen (thanks ) + 1 , MSG_NOSIGNAL );
159
+ printf ("Sent to client: %s, %d bytes\n" , thanks , sent );
160
+ }
161
+ else
162
+ {
163
+ int sent = send (newsocket , denied , strlen (denied ) + 1 , MSG_NOSIGNAL );
164
+ printf ("Sent to client: %s, %d bytes\n" , denied , sent );
165
+ }
166
+ }
167
+ else if (strncmp (command , "HOROSCOPE " , 10 ) == 0 )
168
+ {
169
+ // Send 80 bytes description
170
+ if (desc_index > -1 )
171
+ {
172
+ if (strlen (descriptions [desc_index ]) > 1 )
173
+ {
174
+ int sent = send (newsocket , descriptions [desc_index ], sizeof (descriptions [desc_index ]), MSG_NOSIGNAL );
175
+ printf ("Sent to client: %s, %d bytes\n" , descriptions [desc_index ], sent );
176
+ }
177
+ else
178
+ {
179
+ int sent = send (newsocket , sorry , strlen (sorry ) + 1 , MSG_NOSIGNAL );
180
+ printf ("Sent to client: %s, %d bytes\n" , sorry , sent );
181
+ }
182
+ }
183
+ else
184
+ {
185
+ int sent = send (newsocket , denied , strlen (denied ) + 1 , MSG_NOSIGNAL );
186
+ printf ("Sent to client: %s, %d bytes\n" , denied , sent );
187
+ }
188
+ }
189
+ }
190
+
191
+ printf ("Connection to client closed!" );
192
+ close (newsocket );
193
+ }
194
+
195
+ printf ("Server stopped!" );
196
+ close (sockfd );
197
+ exit (0 );
198
+ }
0 commit comments