Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3fe656c

Browse files
author
Anton Yarkov
committed
Examples of sync and multiplexed async tcp server and client which implements training algorithm/protocol - getting and posting Astrological forecasts.
1 parent 8a17484 commit 3fe656c

File tree

6 files changed

+1349
-0
lines changed

6 files changed

+1349
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <strings.h>
5+
#include <sys/types.h>
6+
#include <sys/socket.h>
7+
#include <arpa/inet.h>
8+
#include <netinet/in.h>
9+
#include <fcntl.h>
10+
#include <netdb.h>
11+
#include <unistd.h>
12+
13+
#define PORTNUM 1500 // Port > 1024 because program will not work not as root.
14+
15+
// Task:
16+
// Create a test TCP-client which sends commands to TCP-server:
17+
// HOROSCOPE - get astrological forecasts from server.
18+
// STARS SAY - send forecast to server.
19+
20+
// Function read number of bytes and return it. It is necessary to use such a function for read,
21+
// because system call recv may return not full response and it will be necessary to read in loop.
22+
ssize_t receive_all(int fd, char *buf, size_t len)
23+
{
24+
size_t pos = 0;
25+
26+
while (pos < len)
27+
{
28+
// Buffer returned by system call recv - is not the string, so we can't use string functions with it.
29+
ssize_t received = recv(fd, buf + pos, len - pos, MSG_NOSIGNAL); // Receive byte by byte.
30+
31+
if (received == -1) return -1;
32+
else if (received == 0) return pos;
33+
else if (received > 0) pos += received;
34+
}
35+
36+
return pos;
37+
}
38+
39+
void main(int argc, char **argv)
40+
{
41+
struct hostent *hp;
42+
if ((hp = gethostbyname(argv[1])) == 0)
43+
{
44+
perror("Error of calling gethostbyname"); /* or strerror */
45+
exit(1);
46+
}
47+
48+
struct sockaddr_in serv_addr;
49+
memset(&serv_addr, '0円', sizeof(serv_addr));
50+
bcopy(hp->h_addr_list[0], &serv_addr.sin_addr, hp->h_length);
51+
serv_addr.sin_family = hp->h_addrtype;
52+
serv_addr.sin_port = htons(PORTNUM);
53+
54+
int sockfd = -1;
55+
if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
56+
{
57+
perror("Error of calling socket");
58+
exit(1);
59+
}
60+
61+
fprintf(stderr, "Server address: %s\n", inet_ntoa(serv_addr.sin_addr));
62+
63+
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
64+
{
65+
perror("Error of calling connect");
66+
exit(1);
67+
}
68+
69+
int testStep = (*argv[2]) - '0';
70+
printf("testStep: %d\n", testStep);
71+
72+
if (testStep == 1)
73+
{
74+
// TEST1. Set some HOROSCOPE.
75+
76+
char setzodiak[] = "STARS SAY Aries ";
77+
int sent = send(sockfd, setzodiak, strlen(setzodiak) + 1, MSG_NOSIGNAL);
78+
printf("Sent to server: %s, %d bytes\n", setzodiak, sent);
79+
80+
char desc[] = "Some of my descriptions here. ";
81+
sent = send(sockfd, desc, strlen(desc) + 1, MSG_NOSIGNAL);
82+
printf("Sent to server: %s, %d bytes\n", desc, sent);
83+
84+
char thanks[10];
85+
memset(thanks, '0円', 10);
86+
int received = receive_all(sockfd, thanks, 10);
87+
printf("Received from server: %d bytes\n", received);
88+
if (received > 0)
89+
{
90+
printf("Received from server: %s\n", thanks);
91+
}
92+
}
93+
else if (testStep == 2)
94+
{
95+
// TEST2. Get HOROSCOPE which was set.
96+
char getzodiak[] = "HOROSCOPE Aries ";
97+
int sent = send(sockfd, getzodiak, strlen(getzodiak) + 1, MSG_NOSIGNAL);
98+
printf("Sent to server: %s, %d bytes\n", getzodiak, sent);
99+
100+
char horoscope[80];
101+
memset(horoscope, '0円', 80);
102+
int received = receive_all(sockfd, horoscope, 80);
103+
printf("Received from server: %d bytes\n", received);
104+
if (received > 0)
105+
{
106+
printf("Received from server: %s\n", horoscope);
107+
}
108+
}
109+
else if (testStep == 3)
110+
{
111+
// TEST3. Good COMMAND, Bad attributes.
112+
char getzodiak[] = "HOROSCOPE Abracadabra";
113+
int sent = send(sockfd, getzodiak, strlen(getzodiak) + 1, MSG_NOSIGNAL);
114+
printf("Sent to server: %s, %d bytes\n", getzodiak, sent);
115+
116+
char denied[10];
117+
memset(denied, '0円', 10);
118+
int received = receive_all(sockfd, denied, 10);
119+
printf("Received from server: %d bytes\n", received);
120+
if (received > 0)
121+
{
122+
printf("Received from server: %s\n", denied);
123+
}
124+
}
125+
else if (testStep == 4)
126+
{
127+
// TEST4. Wrong COMMAND.
128+
char wrongCommand[] = "ABRA CADABRA BOOM BOOM";
129+
int sent = send(sockfd, wrongCommand, strlen(wrongCommand) + 1, MSG_NOSIGNAL);
130+
printf("Sent to server: %s, %d bytes\n", wrongCommand, sent);
131+
132+
char denied[10];
133+
memset(denied, '0円', 10);
134+
int received = receive_all(sockfd, denied, 10);
135+
printf("Received from server: %d bytes\n", received);
136+
}
137+
138+
close(sockfd);
139+
printf("Client off!\n\n"); \
140+
}
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
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

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /