Skip to content

Commit e8b2cde

Browse files
committed
补充socket编程的例子
1 parent 7715070 commit e8b2cde

File tree

1 file changed

+220
-0
lines changed

1 file changed

+220
-0
lines changed

source/basic/network/Socket-Programming-Basic.md

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,226 @@ Socket 还可以认为是一种网络间不同计算机上的进程通信的一
77

88
Socket 起源于 Unix ,Unix/Linux 基本哲学之一就是“一切皆文件”,都可以用“打开(open) –> 读写(write/read) –> 关闭(close)”模式来进行操作。因此 Socket 也被处理为一种特殊的文件。
99

10+
## 写一个简易的 WebServer
11+
12+
一个简易的 Server 的流程如下:
13+
14+
- 1.建立连接,接受一个客户端连接。
15+
- 2.接受请求,从网络中读取一条 HTTP 请求报文。
16+
- 3.处理请求,访问资源。
17+
- 4.构建响应,创建带有 header 的 HTTP 响应报文。
18+
- 5.发送响应,传给客户端。
19+
20+
省略流程 3,大体的程序与调用的函数逻辑如下:
21+
22+
- socket() 创建套接字
23+
- bind() 分配套接字地址
24+
- listen() 等待连接请求
25+
- accept() 允许连接请求
26+
- read()/write() 数据交换
27+
- close() 关闭连接
28+
29+
代码如下:
30+
31+
```cpp
32+
#include <cstdio>
33+
#include <cstdlib>
34+
#include <cstring>
35+
#include <unistd.h>
36+
#include <sys/socket.h>
37+
#include <arpa/inet.h>
38+
#include <string>
39+
#include <cstring>
40+
#include <iostream>
41+
42+
using namespace std;
43+
44+
const int port = 9090;
45+
const int buffer_size = 1<<20;
46+
const int method_size = 1<<10;
47+
const int filename_size = 1<<10;
48+
const int common_buffer_size = 1<<10;
49+
50+
void handleError(const string &message);
51+
void requestHandling(int *sock);
52+
void sendError(int *sock);
53+
void sendData(int *sock, char *filename);
54+
void sendHTML(int *sock, char *filename);
55+
void sendJPG(int *sock, char *filename);
56+
57+
int main()
58+
{
59+
int server_sock;
60+
int client_sock;
61+
62+
struct sockaddr_in server_address;
63+
struct sockaddr_in client_address;
64+
65+
socklen_t client_address_size;
66+
67+
server_sock = socket(PF_INET, SOCK_STREAM, 0);
68+
69+
if (server_sock == -1)
70+
{
71+
handleError("socket error");
72+
}
73+
74+
memset(&server_address,0,sizeof(server_address));
75+
server_address.sin_family = AF_INET;
76+
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
77+
server_address.sin_port = htons(port);
78+
79+
if(bind(server_sock,(struct sockaddr*)&server_address, sizeof(server_address)) == -1){
80+
handleError("bind error");
81+
}
82+
83+
if(listen(server_sock, 5) == -1) {
84+
handleError("listen error");
85+
}
86+
87+
while(true) {
88+
client_address_size = sizeof(client_address);
89+
client_sock = accept(server_sock, (struct sockaddr*) &client_address, &client_address_size);
90+
91+
if (client_sock == -1) {
92+
handleError("accept error");
93+
}
94+
requestHandling(&client_sock);
95+
}
96+
97+
//system("open http://127.0.0.1:9090/index.html");
98+
close(server_sock);
99+
100+
return 0;
101+
}
102+
103+
void requestHandling(int *sock){
104+
int client_sock = *sock;
105+
char buffer[buffer_size];
106+
char method[method_size];
107+
char filename[filename_size];
108+
109+
read(client_sock, buffer, sizeof(buffer)-1);
110+
111+
if(!strstr(buffer, "HTTP/")) {
112+
sendError(sock);
113+
close(client_sock);
114+
return;
115+
}
116+
117+
strcpy(method, strtok(buffer," /"));
118+
strcpy(filename, strtok(NULL, " /"));
119+
120+
if(0 != strcmp(method, "GET")) {
121+
sendError(sock);
122+
close(client_sock);
123+
return;
124+
}
125+
126+
sendData(sock, filename);
127+
}
128+
129+
void sendData(int *sock, char *filename) {
130+
int client_sock = *sock;
131+
char buffer[common_buffer_size];
132+
char type[common_buffer_size];
133+
134+
strcpy(buffer, filename);
135+
136+
strtok(buffer, ".");
137+
strcpy(type, strtok(NULL, "."));
138+
139+
if(0 == strcmp(type, "html")){
140+
sendHTML(sock, filename);
141+
}else if(0 == strcmp(type, "jpg")){
142+
sendJPG(sock, filename);
143+
}else{
144+
sendError(sock);
145+
close(client_sock);
146+
return ;
147+
}
148+
}
149+
150+
void sendHTML(int *sock, char *filename) {
151+
int client_sock = *sock;
152+
char buffer[buffer_size];
153+
FILE *fp;
154+
155+
char status[] = "HTTP/1.0 200 OK\r\n";
156+
char header[] = "Server: A Simple Web Server\r\nContent-Type: text/html\r\n\r\n";
157+
158+
write(client_sock, status, strlen(status));
159+
write(client_sock, header, strlen(header));
160+
161+
fp = fopen(filename, "r");
162+
if(!fp){
163+
sendError(sock);
164+
close(client_sock);
165+
handleError("failed to open file");
166+
return ;
167+
}
168+
169+
fgets(buffer,sizeof(buffer), fp);
170+
while(!feof(fp)) {
171+
write(client_sock, buffer, strlen(buffer));
172+
fgets(buffer, sizeof(buffer), fp);
173+
}
174+
175+
fclose(fp);
176+
close(client_sock);
177+
}
178+
179+
void sendJPG(int *sock, char *filename) {
180+
int client_sock = *sock;
181+
char buffer[buffer_size];
182+
FILE *fp;
183+
FILE *fw;
184+
185+
char status[] = "HTTP/1.0 200 OK\r\n";
186+
char header[] = "Server: A Simple Web Server\r\nContent-Type: image/jpeg\r\n\r\n";
187+
188+
write(client_sock, status, strlen(status));
189+
write(client_sock, header, strlen(header));
190+
191+
fp = fopen(filename, "rb");
192+
if(NULL == fp){
193+
sendError(sock);
194+
close(client_sock);
195+
handleError("failed to open file");
196+
return ;
197+
}
198+
199+
fw = fdopen(client_sock, "w");
200+
fread(buffer, 1, sizeof(buffer), fp);
201+
while (!feof(fp)){
202+
fwrite(buffer, 1, sizeof(buffer), fw);
203+
fread(buffer, 1, sizeof(buffer), fp);
204+
}
205+
206+
fclose(fw);
207+
fclose(fp);
208+
close(client_sock);
209+
}
210+
211+
void handleError(const string &message) {
212+
cout<<message;
213+
exit(1);
214+
}
215+
216+
void sendError(int *sock){
217+
int client_sock = *sock;
218+
219+
char status[] = "HTTP/1.0 400 Bad Request\r\n";
220+
char header[] = "Server: A Simple Web Server\r\nContent-Type: text/html\r\n\r\n";
221+
char body[] = "<html><head><title>Bad Request</title></head><body><p>400 Bad Request</p></body></html>";
222+
223+
write(client_sock, status, sizeof(status));
224+
write(client_sock, header, sizeof(header));
225+
write(client_sock, body, sizeof(body));
226+
}
227+
```
228+
229+
10230
### 参考资料
11231
12232
1. [Linux Socket编程](http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html)

0 commit comments

Comments
 (0)