-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest.c
190 lines (172 loc) · 9.19 KB
/
test.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/**************************************************************************/
/* Header files needed for this sample program */
/**************************************************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
/**************************************************************************/
/* Constants used by this program */
/**************************************************************************/
#define SERVER_PORT 3005
#define BUFFER_LENGTH 250
#define FALSE 0
int main() {
/***********************************************************************/
/* Variable and structure definitions. */
/***********************************************************************/
int sd=-1, sdconn=-1;
int rc, on=1, rcdsize=BUFFER_LENGTH;
char buffer[BUFFER_LENGTH];
struct sockaddr_in6 serveraddr, clientaddr;
unsigned int addrlen=sizeof(clientaddr);
char str[INET6_ADDRSTRLEN];
/***********************************************************************/
/* A do/while(FALSE) loop is used to make error cleanup easier. The */
/* close() of each of the socket descriptors is only done once at the */
/* very end of the program. */
/***********************************************************************/
do {
/********************************************************************/
/* The socket() function returns a socket descriptor, which represents */
/* an endpoint. Get a socket for address family AF_INET6 to */
/* prepare to accept incoming connections on. */
/********************************************************************/
if ((sd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
perror("socket() failed");
break;
}
/********************************************************************/
/* The setsockopt() function is used to allow the local address to */
/* be reused when the server is restarted before the required wait */
/* time expires. */
/********************************************************************/
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,
(char *)&on,sizeof(on)) < 0) {
perror("setsockopt(SO_REUSEADDR) failed");
break;
}
/********************************************************************/
/* After the socket descriptor is created, a bind() function gets a */
/* unique name for the socket. In this example, the user sets the */
/* address to in6addr_any, which (by default) allows connections to */
/* be established from any IPv4 or IPv6 client that specifies port */
/* 3005. (that is, the bind is done to both the IPv4 and IPv6 TCP/IP */
/* stacks). This behavior can be modified using the IPPROTO_IPV6 */
/* level socket option IPV6_V6ONLY if required. */
/********************************************************************/
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin6_family = AF_INET6;
serveraddr.sin6_port = htons(SERVER_PORT);
/********************************************************************/
/* Note: applications use in6addr_any similarly to the way they use */
/* INADDR_ANY in IPv4. A symbolic constant IN6ADDR_ANY_INIT also */
/* exists but can only be used to initialize an in6_addr structure */
/* at declaration time (not during an assignment). */
/********************************************************************/
serveraddr.sin6_addr = in6addr_any;
/********************************************************************/
/* Note: the remaining fields in the sockaddr_in6 are currently not */
/* supported and should be set to 0 to ensure upward compatibility. */
/********************************************************************/
if (bind(sd,
(struct sockaddr *)&serveraddr,
sizeof(serveraddr)) < 0) {
perror("bind() failed");
break;
}
/********************************************************************/
/* The listen() function allows the server to accept incoming */
/* client connections. In this example, the backlog is set to 10. */
/* This means that the system will queue 10 incoming connection */
/* requests before the system starts rejecting the incoming */
/* requests. */
/********************************************************************/
if (listen(sd, 10) < 0) {
perror("listen() failed");
break;
}
printf("Ready for client connect().\n");
printf("sizeof sockaddr %lu\n",sizeof(struct sockaddr));
printf("sizeof sockaddr_in %lu\n",sizeof(struct sockaddr_in));
printf("sizeof sockaddr_in6 %lu\n",sizeof(struct sockaddr_in6));
printf("sizeof sockaddr_un %lu\n",sizeof(struct sockaddr_un));
printf("sizeof sockaddr_storage %lu\n",sizeof(struct sockaddr_storage));
/********************************************************************/
/* The server uses the accept() function to accept an incoming */
/* connection request. The accept() call will block indefinitely */
/* waiting for the incoming connection to arrive from an IPv4 or */
/* IPv6 client. */
/********************************************************************/
if ((sdconn = accept(sd, NULL, NULL)) < 0) {
perror("accept() failed");
break;
} else {
/*****************************************************************/
/* Display the client address. Note that if the client is */
/* an IPv4 client, the address will be shown as an IPv4 Mapped */
/* IPv6 address. */
/*****************************************************************/
getpeername(sdconn, (struct sockaddr *)&clientaddr, &addrlen);
if(inet_ntop(AF_INET6, &clientaddr.sin6_addr, str, sizeof(str))) {
printf("Client address is %s\n", str);
printf("Client port is %d\n", ntohs(clientaddr.sin6_port));
}
}
/********************************************************************/
/* In this example we know that the client will send 250 bytes of */
/* data over. Knowing this, we can use the SO_RCVLOWAT socket */
/* option and specify that we don't want our recv() to wake up */
/* until all 250 bytes of data have arrived. */
/********************************************************************/
if (setsockopt(sdconn, SOL_SOCKET, SO_RCVLOWAT,
(char *)&rcdsize,sizeof(rcdsize)) < 0) {
perror("setsockopt(SO_RCVLOWAT) failed");
break;
}
/********************************************************************/
/* Receive that 250 bytes of data from the client */
/********************************************************************/
rc = recv(sdconn, buffer, sizeof(buffer), 0);
if (rc < 0) {
perror("recv() failed");
break;
}
printf("%d bytes of data were received\n", rc);
if (rc == 0 ||
rc < sizeof(buffer)) {
printf("The client closed the connection before all of the\n");
printf("data was sent\n");
break;
}
/********************************************************************/
/* Echo the data back to the client */
/********************************************************************/
rc = send(sdconn, buffer, sizeof(buffer), 0);
if (rc < 0) {
perror("send() failed");
break;
}
/********************************************************************/
/* Program complete */
/********************************************************************/
} while (FALSE);
/***********************************************************************/
/* Close down any open socket descriptors */
/***********************************************************************/
if (sd != -1)
close(sd);
if (sdconn != -1)
close(sdconn);
}
// Local Variables: ***
// mode: C++ ***
// tab-width: 3 ***
// c-basic-offset: 3 ***
// indent-tabs-mode: nil ***
// End: ***
// ex: shiftwidth=4 tabstop=4