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
191
| #include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h> //互联网地址族
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <ctype.h> //toupper (小写转化为大写)
// int port = 8000;
// char *server = "localhost";
char *server = "127.0.0.1";
void PrintSocketAddress(const struct sockaddr *address, FILE *stream) {
// Test for address and stream
if (address == NULL || stream == NULL)
return;
void *numericAddress; // Pointer to binary address
// Buffer to contain result (IPv6 sufficient to hold IPv4)
char addrBuffer[INET6_ADDRSTRLEN];
in_port_t port; // Port to print
// Set pointer to address based on address family
switch (address->sa_family) {
case AF_INET:
numericAddress = &((struct sockaddr_in *) address)->sin_addr;
port = ntohs(((struct sockaddr_in *) address)->sin_port);
break;
case AF_INET6:
numericAddress = &((struct sockaddr_in6 *) address)->sin6_addr;
port = ntohs(((struct sockaddr_in6 *) address)->sin6_port);
break;
default:
fputs("[unknown type]", stream); // Unhandled type
return;
}
// Convert binary to printable address
if (inet_ntop(address->sa_family, numericAddress, addrBuffer,
sizeof(addrBuffer)) == NULL)
fputs("[invalid address]", stream); // Unable to convert
else {
fprintf(stream, "%s", addrBuffer);
if (port != 0) // Zero not valid in any socket addr
fprintf(stream, "-%u", port);
}
}
int create_socket(char *servername, char *port)
{
int sockfd = 0;
int address_size;
struct addrinfo hints;
struct addrinfo *result;
int i, len;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
int s = getaddrinfo(servername, port, &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
//socket函数,向系统申请一个通信端口
sockfd = socket(result->ai_family, result->ai_socktype, 0); //IPV4 TCP协议
if (sockfd == -1) //申请失败
{
perror("call to socket");
exit(1);
}
//将套接字(sin) 跟端口(sockfd)链接
if (bind(sockfd, result->ai_addr, result->ai_addrlen) == -1)
{
perror("call to bind");
exit(1);
}
struct sockaddr_storage local_addr;
socklen_t addr_size=sizeof(local_addr);
if(getsockname(sockfd,(struct sockaddr *)&local_addr,&addr_size)<0)
{
// DieWithSystemMessage("getsockname() failed!");
}
fputs("Binding to ",stdout);
PrintSocketAddress((struct sockaddr*)&local_addr,stdout);
freeaddrinfo(result);
/*int PASCAL FAR listen( SOCKET s, int backlog);
S:用于标识一个已捆绑未连接套接口的描述字。
backlog:等待连接队列的最大长度。
* listen()仅适用于支持连接的套接口,如SOCK_STREAM类型的。
*/
if (listen(sockfd, 20) == -1) //在端口sockfd监听
{
perror("call to listen");
exit(1);
}
printf("accepting connections \n");
return sockfd;
}
/*服务端*/
int main(int argc, char **argv)
{
int sock_descriptor = create_socket(argv[1], "8000");
int temp_sock_descriptor;
int address_size;
char buf[16384]; // 缓冲区大小
struct sockaddr_storage pin;
address_size = sizeof(pin);
int i, len;
while (1)
{ //用来监听的端口sock_descriptor
temp_sock_descriptor = accept(sock_descriptor, (struct sockaddr *)&pin, &address_size);
if (temp_sock_descriptor == -1)
{
perror("call to accept");
exit(1);
}
/*int PASCAL FAR recv( SOCKET s, char FAR* buf, int len, int flags);
s:一个标识已连接套接口的描述字。
buf:用于接收数据的缓冲区。
len:缓冲区长度。
flags:指定调用方式。
*/
printf("wait to recv message\n");
struct timeval tv;
// Set up the struct timeval for the timeout.
tv.tv_sec = 30;
tv.tv_usec = 0;
// 添加socket延时
// setsockopt(temp_sock_descriptor, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
if (recv(temp_sock_descriptor, buf, 16384, 0) == -1)
{
perror("call to recv");
exit(1);
}
printf("received from client:%s\n", buf);
len = strlen(buf);
for (i = 0; i < len; i++)
{
buf[i] = toupper(buf[i]); //将小写字母转化为大写字母
}
/*int PASCAL FAR send( SOCKET s, const char FAR* buf, int len, int flags);
s:一个用于标识已连接套接口的描述字。
buf:包含待发送数据的缓冲区。
len:缓冲区中数据的长度。
flags:调用执行方式。*/
/*send() 基于链接的发送 TCP
*sendto() 基于无链接到 UDP
*/
if (send(temp_sock_descriptor, buf, len, 0) == -1)
{
perror("call to send");
exit(1);
}
close(temp_sock_descriptor);
}
return (EXIT_SUCCESS);
}
|