-
Notifications
You must be signed in to change notification settings - Fork 0
/
TCPServer-ex2.c
159 lines (139 loc) · 4.41 KB
/
TCPServer-ex2.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
NAME: TCPServer
SYNOPSIS: TCPServer [port]
DESCRIPTION: The program creates a TCP socket in the inet
listen for connections from TCPClients,
accept clients into private sockets, and
fork an echo process to ``serve'' the client.
If [port] is not specified, the program uses any available port.
*/
#include <stdio.h>
/* socket(), bind(), recv, send */
#include <sys/types.h>
#include <sys/socket.h> /* sockaddr_in */
#include <netinet/in.h> /* inet_addr() */
#include <arpa/inet.h>
#include <netdb.h> /* struct hostent */
#include <string.h> /* memset() */
#include <unistd.h> /* close() */
#include <stdlib.h> /* exit() */
#define MAXHOSTNAME 80
void reusePort(int sock);
void EchoServe(int psd, struct sockaddr_in from);
int main(int argc, char **argv ) {
int sd, psd;
struct sockaddr_in server;
struct hostent *hp, *gethostbyname();
struct servent *sp;
struct sockaddr_in from;
int fromlen;
int length;
char ThisHost[80];
int pn;
int childpid;
sp = getservbyname("echo", "tcp");
/* get TCPServer1 Host information, NAME and INET ADDRESS */
gethostname(ThisHost, MAXHOSTNAME);
/* OR strcpy(ThisHost,"localhost"); */
printf("----TCP/Server running at host NAME: %s\n", ThisHost);
if ( (hp = gethostbyname(ThisHost)) == NULL ) {
fprintf(stderr, "Can't find host %s\n", argv[1]);
exit(-1);
}
bcopy ( hp->h_addr, &(server.sin_addr), hp->h_length);
printf(" (TCP/Server INET ADDRESS is: %s )\n", inet_ntoa(server.sin_addr));
/** Construct name of socket */
server.sin_family = AF_INET;
/* OR server.sin_family = hp->h_addrtype; */
server.sin_addr.s_addr = inet_addr("127.0.0.1");
if (argc == 1)
server.sin_port = htons(0);
else {
pn = htons(atoi(argv[1]));
server.sin_port = pn;
}
/*OR server.sin_port = sp->s_port; */
/** Create socket on which to send and receive */
sd = socket (AF_INET,SOCK_STREAM,IPPROTO_TCP);
/* OR sd = socket (hp->h_addrtype,SOCK_STREAM,0); */
if (sd<0) {
perror("opening stream socket");
exit(-1);
}
/** this allow the server to re-start quickly instead of fully wait
for TIME_WAIT which can be as large as 2 minutes */
reusePort(sd);
if ( bind( sd, (struct sockaddr *) &server, sizeof(server) ) < 0 ) {
close(sd);
perror("binding name to stream socket");
exit(-1);
}
/** get port information and prints it out */
length = sizeof(server);
if ( getsockname (sd, (struct sockaddr *)&server,&length) ) {
perror("getting socket name");
exit(0);
}
printf("Server Port is: %d\n", ntohs(server.sin_port));
/** accept TCP connections from clients and fork a process to serve each */
listen(sd,4);
fromlen = sizeof(from);
for(;;){
psd = accept(sd, (struct sockaddr *)&from, &fromlen);
childpid = fork();
if ( childpid == 0) {
close (sd);
EchoServe(psd, from);
}
else{
printf("My new child pid is %d\n", childpid);
close(psd);
}
}
}
void EchoServe(int psd, struct sockaddr_in from) {
char buf[512];
int rc;
struct hostent *hp, *gethostbyname();
printf("Serving %s:%d\n", inet_ntoa(from.sin_addr),
ntohs(from.sin_port));
if ((hp = gethostbyaddr((char *)&from.sin_addr.s_addr,
sizeof(from.sin_addr.s_addr),AF_INET)) == NULL)
fprintf(stderr, "Can't find host %s\n", inet_ntoa(from.sin_addr));
else
printf("(Name is : %s)\n", hp->h_name);
/** get data from clients and send it back */
for(;;){
printf("\n...server is waiting...\n");
if( (rc=recv(psd, buf, sizeof(buf), 0)) < 0){
perror("receiving stream message");
exit(-1);
}
if (rc > 0){
buf[rc]='\0';
printf("Received: %s\n", buf);
printf("From TCP/Client: %s:%d\n", inet_ntoa(from.sin_addr),
ntohs(from.sin_port));
printf("(Name is : %s)\n", hp->h_name);
if (send(psd, buf, rc, 0) <0 )
perror("sending stream message");
}
else {
printf("TCP/Client: %s:%d\n", inet_ntoa(from.sin_addr),
ntohs(from.sin_port));
printf("(Name is : %s)\n", hp->h_name);
printf("Disconnected..\n");
close (psd);
exit(0);
}
}
}
void reusePort(int s)
{
int one=1;
if ( setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *) &one,sizeof(one)) == -1 )
{
printf("error in setsockopt,SO_REUSEPORT \n");
exit(-1);
}
}