/**************filename:server.cpp****************
The program implements a simple HTTP server through a standard socket
Running the server can access the server directory through the browser
HTML files and JPG Images complete the initial HTTP server functionality
***************************************************/
#include <winsock.h>
#include <sys/stat.h>
#include <iostream>
using namespace Std;
#define SERVER_PORT 10000//Custom service port
#define HOSTLEN 256//Host name length
#define BACKLOG 10//number of simultaneous waiting connections
/**************************************
The method wraps the Send ()
Sending the data through this method can all be emitted
No omissions.
**************************************/
int Sendall (int s, char *buf, int *len) {
int total = 0; Number of bytes already sent
int bytesleft = *len; How many bytes are left?
int n;
while (Total < *len) {
n = Send (S, buf+total, Bytesleft, 0);
if (n = =-1) {break;}
Total + = n;
Bytesleft-= n;
}
*len = total; Returns the number of bytes actually sent out
return n==-1?-1:0; Successful send returned 0 failed-1
}
/**************************************
The method handles the error request
and sends an error message to the client
**************************************/
void Wrong_req (int sock) {
char* error_head = "http/1.0 501 not implemented\r\n"; Output 501 Error
int len = strlen (Error_head);
if (Sendall (sock, error_head, &len) = =-1) {//Send to Customer
printf ("Sending failed!");
Return
}
char* Error_type = "content-type:text/plain\r\n";
Len = strlen (Error_type);
if (Sendall (sock, error_type, &len) = =-1) {
printf ("Sending failed!");
Return
}
char* error_end = "\ r \ n";
Len = strlen (error_end);
if (Sendall (sock, error_end, &len) = =-1) {
printf ("Sending failed!");
Return
}
char* prompt_info = "The command is not yet completed\r\n";
Len = strlen (prompt_info);
if (Sendall (sock, prompt_info, &len) = =-1) {
printf ("Sending failed!");
Return
}
}
/**********************************
This method determines whether the file requested by the user exists
Not present returns True existence returns False
***********************************/
BOOL Not_exit (char* arguments) {
struct stat dir_info;
Return (stat (arguments, &dir_info) = =-1);
}
/*************************************
The requested file does not exist
*************************************/
void File_not_found (char* arguments, int sock) {
char* error_head = "http/1.0 404 Not Found\r\n"; Construct 404 Error head
int len = strlen (Error_head);
if (Sendall (sock, error_head, &len) = =-1) {//Send to Client
printf ("Sending error!");
Return
}
char* Error_type = "content-type:text/plain\r\n";
Len = strlen (Error_type);
if (Sendall (sock, error_type, &len) = =-1) {
printf ("Sending error!");
Return
}
char* error_end = "\ r \ n";
Len = strlen (error_end);
if (Sendall (sock, error_end, &len) = =-1) {
printf ("Sending error!");
Return
}
Char prompt_info[50] = "not Found:";
strcat (prompt_info, arguments);
Len = strlen (prompt_info);
if (Sendall (sock, prompt_info, &len) = =-1) {//Output files not found
printf ("Sending error!");
Return
}
}
/*************************************
Send HTTP protocol header information
These include the response type and the content type
*************************************/
void Send_header (int send_to, char* content_type) {
char* head = "http/1.0 ok\r\n"; The right header information
int len = strlen (head);
if (Sendall (send_to, head, &len) = =-1) {//Send data to the connected client
printf ("Sending error");
Return
}
if (content_type) {//content_type is not empty
Char temp_1[30] = "Content-type:"; Prepare the string you want to connect to
strcat (Temp_1, Content_Type); Construction Content_Type
strcat (temp_1, "\ r \ n");
Len = strlen (temp_1);
if (Sendall (send_to, temp_1, &len) = =-1) {
printf ("Sending error!");
Return
}
}
}
/***********************************
Get the file type requested by the user
That is, the file suffix (. html. jpg. gif)
************************************/
char* File_type (char* Arg) {
char * TEMP; Temporary string pointer
if (TEMP=STRRCHR (ARG, '. ')) = NULL) {//Get suffix
return temp+1;
}
Return ""; If the file name is not in the request. The empty string is returned
}
/*************************************
This method is the core of the program
Responsible for really sending files such as *.html *.jpg etc.
*************************************/
void Send_file (char* arguments, int sock) {
char* extension = file_type (arguments); Get the file suffix name
char* content_type = "Text/plain"; Initialize type= ' Text/plain '
File* Read_from; The local file pointer reads from the file. html. jpg, etc.
int readed =-1; Number of bytes per read
if (strcmp (extension, "html") = = = 0) {//Send content as HTML
Content_Type = "text/html";
}
if (strcmp (extension, "gif") = = 0) {//Send content as GIF
Content_Type = "Image/gif";
}
if (strcmp (extension, "jpg") = = = 0) {//send content as JPG
Content_Type = "Image/jpg";
}
Read_from = fopen (arguments, "R"); Open user-specified file ready to read
if (read_from! = NULL) {//Pointer not empty
Char read_buf[128]; Byte Cache array when reading a file
Send_header (sock, Content_Type); Send Protocol Header
Send (sock, "\ r \ n", 2, 0); Add a "\ r \ n" cannot lack the format requirement
while (!feof (Read_from)) {//Determines whether the file has ended
Fgets (Read_buf, Read_from); Read
int len = strlen (READ_BUF);
if (Sendall (sock, read_buf, &len) = =-1) {//Send data
printf ("Sending error!"); A send error appears to the console to continue sending
Continue
}
}
}
}
/***********************************
Parse and process user requests
***********************************/
void Handle_req (char* request, int client_sock) {
Char Command[bufsiz]; Save resolved to a command field get PUT
Char Arguments[bufsiz]; Save the file to which the request was resolved
/*
* Add the current directory symbol before user request
*/
strcpy (arguments, "./"); Note the difference between the symbols in different operating systems
/*
* Parse Request
*/
if (sscanf (Request, "%s%s", command, arguments+2)! = 2) {
Return Parse Error in return
}
printf ("Handle_cmd:%s\n", command); Output This command to the console
printf ("Handle_path:%s\n", arguments); To output the request path at this time to the console
if (strcmp (command, "GET")! = 0) {//Request command format is correct
Wrong_req (Client_sock);
Return
}
if (not_exit (arguments)) {//The requested file exists
File_not_found (arguments, client_sock);
Return
}
Send_file (arguments, client_sock); Send data when command format and request path are correct
Return
}
/*************************************
This method constructs a server-side socket
Returns the constructed socket descriptor
*************************************/
int Make_server_socket () {
struct sockaddr_in server_addr; Server address structure body
int tempsockid; Temporarily store the socket descriptor
Tempsockid = socket (pf_inet, sock_stream, 0);
if (Tempsockid = =-1) {//error if return value is-1
return-1;
}
/*
* Populate Server connection information
*/
server_addr.sin_family = af_inet;
Server_addr.sin_port = htons (Server_port);
SERVER_ADDR.SIN_ADDR.S_ADDR = inet_addr ("127.0.0.1"); Local address
memset (& (Server_addr.sin_zero), ' + ', 8);
if (bind (tempsockid, struct sockaddr *) &server_addr,
sizeof (SERVER_ADDR)) = =-1) {//Bind service returns 1 if an error occurs
printf ("Bind error!\n");
return-1;
}
if (Listen (Tempsockid, BACKLOG) = =-1) {//start listening
printf ("Listen error!\n");
return-1;
}
return tempsockid; Returns the socket obtained
}
/***********************
Main function Main ()
Program entry
***********************/
void Main (int argc, char * argv[]) {
/*
* Call WSAStartup () for easy access to sockets library
*/
Wsadata Wsadata;
if (WSAStartup (Makeword (1, 1), &wsadata)! = 0) {
fprintf (stderr, "WSAStartup failed.\n");
Exit (1);
}
printf ("My Web server started...\n");
int server_socket; Socket for server
int acc_socket; The socket that receives the user connection
int sock_size = sizeof (struct sockaddr_in);
struct sockaddr_in user_socket; Customer connection Information
Server_socket = Make_server_socket (); Create a server-side socket
if (Server_socket = =-1) {//Create socket Error
printf ("Server exception!\n");
Exit (2);
}
/*
* Main loop
*/
while (true) {
Acc_socket = Accept (Server_socket, (struct sockaddr *) &user_socket, &sock_size); Receive connection
cout << Inet_ntoa (user_socket.sin_addr) << Endl; Test with:-)//
/*
* Read Customer Request
*/
int numbytes;
Char buf[100];
if ((Numbytes=recv (Acc_socket, buf, 99, 0)) = =-1) {
Perror ("recv");
Exit (1);
}
printf ("Buf ...%s", buf); For testing
/*
* Processing user requests
*/
Handle_req (buf, Acc_socket);
}
}
/************** Program End server.cpp******************/
C language-implemented Web server