#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <zconf.h>
#define PORT 8080 // 服務器監聽端口
#define MAX_QUEUE 5 // 待連接的隊列最大數
#define MAX_LEN 1024 // 接收瀏覽器數據
int main(){
int server_socket_fp; // 服務端socket句柄
struct sockaddr_in server_addr; // 地址結構體
char buff[MAX_LEN];
/**
* 創建socket
* AF_INET: IPV4網絡操作
* SOCK_STREAM: 使用TCP協議傳輸數據
* 0: 自動選擇協議
*/
if ((server_socket_fp = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("create socket failed");
exit(EXIT_FAILURE);
}
/**
* 將socket與地址綁定
* bind參數:
* socket描述符
* 地址結構體,需要強轉成struct sockaddr類型
* 結構體長度,傳入的是指針,無法再函數內部獲取長度
*/
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // INADDR_ANY表示任何地址訪問都可以
server_addr.sin_port = htons(PORT); // 端口號
if (bind(server_socket_fp, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
printf("bind socket with addr struct failed!");
exit(EXIT_FAILURE);
}
/**
* 監聽鏈接
* 參數:
* socket描述符
* 待連接隊列的最大個數,一般為5
*/
listen(server_socket_fp, MAX_QUEUE);
/**
* 與客戶端建立連接
* 參數:
* socket文件描述符
* 客戶端地址信息的結構體,不關心可以傳NULL
* 客戶端地址長度,不關心可以傳NULL
* 返回值:
* socket文件描述符,在與客戶端建立連接后,accpet還是會生成一個專門用於和當前客戶端通信的socket,
* 而原來那個socket照常負責和其他等待建立連接的客戶端建立通信
*/
int client_socket_fp = accept(server_socket_fp, NULL, NULL);
/**
* 讀取瀏覽器的內容
* 參數:
* 文件描述符,從哪個文件讀,這里填寫accept返回的文件句柄
* 讀的內容存到buff中
* 共讀多少個字節
*/
read(client_socket_fp, buff, MAX_LEN);
printf("%s", buff);
/**
* 向瀏覽器寫入內容
* 參數:
* 文件描述符,往哪個文件寫,這里填寫accept返回的文件句柄
* 內容的首地址
* 共讀多少個字節
*/
char status[] = "HTTP/1.0 200 OK\r\n";
char header[] = "Server: DWBServer\r\nContent-Type: text/html;charset=utf-8\r\n\r\n";
char body[] = "<html><head><title>C語言構建小型Web服務器</title></head><body><h2>歡迎</h2><p>Hello,World</p></body></html>";
write(client_socket_fp, status, sizeof(status));
write(client_socket_fp, header, sizeof(header));
write(client_socket_fp, body, sizeof(body));
close(client_socket_fp);
close(server_socket_fp);
return 0;
}
原文:https://www.jianshu.com/p/592b631e1ff1