Skip to content

Commit 6fd462e

Browse files
committed
added read me file
0 parents  commit 6fd462e

File tree

6 files changed

+560
-0
lines changed

6 files changed

+560
-0
lines changed

cli/client.cpp

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
#define _CRT_SECURE_NO_WARNINGS
2+
#include <winsock.h>
3+
#include <stdio.h>
4+
#include <iostream>
5+
#include <string.h>
6+
#include <windows.h>
7+
#include <complex>
8+
#include <ctime>
9+
#include <chrono>
10+
using namespace std;
11+
#define HOSTNAME_LENGTH 20
12+
#define RESP_LENGTH 40
13+
#define WEBPAGE_LENGTH 20
14+
#define REQUEST_PORT 5001
15+
#define BUFFER_LENGTH 1024
16+
#define TRACE 0
17+
#define MSGHDRSIZE 8 //Message Header Size
18+
#define TIME_LENGTH 100
19+
#define NUMBER_OF_PARAMETER 5
20+
21+
typedef enum
22+
{
23+
REQ = 1,
24+
RESP //Message type
25+
} Type;
26+
27+
typedef enum
28+
{
29+
GET = 1,
30+
POST //Message type
31+
} HTTP_METHOD;
32+
33+
34+
typedef struct
35+
{
36+
double http_version;
37+
HTTP_METHOD http_method;
38+
char serverHostName[HOSTNAME_LENGTH]; // only used in http 1.1
39+
char hostname[HOSTNAME_LENGTH];
40+
char webPageName[WEBPAGE_LENGTH];
41+
char timeStamp[TIME_LENGTH];
42+
} Req; //request
43+
44+
typedef struct
45+
{
46+
int status_code;
47+
double http_version;
48+
char timeStamp[TIME_LENGTH];
49+
} Resp; //response
50+
51+
52+
typedef struct
53+
{
54+
Type type;
55+
int length; //length of effective bytes in the buffer
56+
char buffer[BUFFER_LENGTH];
57+
} Msg; //message format used for sending and receiving
58+
59+
60+
class TcpClient
61+
{
62+
int sock; /* Socket descriptor */
63+
struct sockaddr_in ServAddr; /* server socket address */
64+
unsigned short ServPort; /* server port */
65+
Req* reqp; /* pointer to request */
66+
Resp* respp; /* pointer to response*/
67+
Msg smsg, rmsg; /* receive_message and send_message */
68+
WSADATA wsadata;
69+
public:
70+
TcpClient()
71+
{
72+
}
73+
void run();
74+
~TcpClient();
75+
int msg_recv(int, Msg*);
76+
int msg_send(int, Msg*);
77+
unsigned long ResolveName(char name[]);
78+
void err_sys(const char* fmt,...);
79+
};
80+
81+
void TcpClient::run()
82+
{
83+
char argv[NUMBER_OF_PARAMETER][WEBPAGE_LENGTH];
84+
char method[HOSTNAME_LENGTH];
85+
struct _stat stat_buf;
86+
87+
//initilize winsocket
88+
if (WSAStartup(0x0202, &wsadata) != 0)
89+
{
90+
WSACleanup();
91+
err_sys("Error in starting WSAStartup()\n");
92+
}
93+
94+
95+
reqp = (Req *)smsg.buffer;
96+
97+
//Display name of local host and copy it to the req
98+
if (gethostname(reqp->hostname,HOSTNAME_LENGTH) != 0) //get the hostname
99+
err_sys("can not get the host name,program exit");
100+
printf("%s%s\n", "Client starting at host:", reqp->hostname);
101+
cout << "Type name of web server:";
102+
scanf("%s", argv[1]); // read server host name
103+
cout << "Requesting web page..\n";
104+
cout << "HTTP version:";
105+
scanf("%lf", &(reqp->http_version));
106+
cout << "Method:";
107+
scanf("%s", method);
108+
109+
if (strcmp(method, "GET") == 0)
110+
reqp->http_method = GET;
111+
else if (strcmp(argv[3], "POST") == 0)
112+
reqp->http_method = POST;
113+
else err_sys("Wrong Method type\n");
114+
smsg.type = REQ;
115+
cout << "Webpage Name:";
116+
//read webpage name
117+
scanf("%s", argv[2]);
118+
strcpy(reqp->webPageName, argv[2]);
119+
120+
121+
memset(reqp->timeStamp, 0, sizeof(reqp->timeStamp));
122+
auto end = std::chrono::system_clock::now();
123+
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
124+
sprintf(reqp->timeStamp, "%s", std::ctime(&end_time));
125+
126+
127+
if(reqp->http_version == 1.1) // set the sever host name only when the version is 1.1
128+
strcpy(reqp->serverHostName, argv[1]);
129+
else memset(reqp->serverHostName, 0, sizeof(reqp->serverHostName));
130+
131+
puts("Webpage requested, waiting for web server to respond... ");
132+
//Create the socket
133+
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) //create the socket
134+
err_sys("Socket Creating Error");
135+
136+
//connect to the server
137+
ServPort = REQUEST_PORT;
138+
memset(&ServAddr, 0, sizeof(ServAddr)); /* Zero out structure */
139+
ServAddr.sin_family = AF_INET; /* Internet address family */
140+
ServAddr.sin_addr.s_addr = ResolveName(argv[1]); /* Server IP address */
141+
ServAddr.sin_port = htons(ServPort); /* Server port */
142+
if (connect(sock, (struct sockaddr *)&ServAddr, sizeof(ServAddr)) < 0)
143+
err_sys("Socket Creating Error");
144+
145+
//send out the message
146+
smsg.length = sizeof(Req);
147+
fprintf(stdout, "Send reqest to %s\n", argv[1]);
148+
if (msg_send(sock, &smsg) != sizeof(Req))
149+
err_sys("Sending req packet error.,exit");
150+
151+
//receive the response
152+
if (msg_recv(sock, &rmsg) != rmsg.length)
153+
err_sys("recv response error,exit");
154+
155+
//cast it to the response structure
156+
respp = (Resp *)rmsg.buffer;
157+
printf("HTTP response to your request is %s, response received at %s \n\n\n",
158+
respp->status_code == 200 ? "[200 OK]" : "[501 Error]", respp->timeStamp);
159+
160+
//close the client socket
161+
closesocket(sock);
162+
}
163+
TcpClient::~TcpClient()
164+
{
165+
/* When done uninstall winsock.dll (WSACleanup()) and exit */
166+
WSACleanup();
167+
}
168+
169+
170+
void TcpClient::err_sys(const char* fmt,...) //from Richard Stevens's source code
171+
{
172+
perror(NULL);
173+
va_list args;
174+
va_start(args,fmt);
175+
fprintf(stderr, "error: ");
176+
vfprintf(stderr, fmt, args);
177+
fprintf(stderr, "\n");
178+
va_end(args);
179+
exit(1);
180+
}
181+
182+
unsigned long TcpClient::ResolveName(char name[])
183+
{
184+
struct hostent* host; /* Structure containing host information */
185+
186+
if ((host = gethostbyname(name)) == NULL)
187+
err_sys("gethostbyname() failed");
188+
189+
/* Return the binary, network byte ordered address */
190+
return *((unsigned long *)host->h_addr_list[0]);
191+
}
192+
193+
/*
194+
msg_recv returns the length of bytes in the msg_ptr->buffer,which have been recevied successfully.
195+
*/
196+
int TcpClient::msg_recv(int sock, Msg* msg_ptr)
197+
{
198+
int rbytes, n;
199+
200+
for (rbytes = 0; rbytes < MSGHDRSIZE; rbytes += n)
201+
if ((n = recv(sock, (char *)msg_ptr + rbytes,MSGHDRSIZE - rbytes, 0)) <= 0)
202+
err_sys("Recv MSGHDR Error");
203+
204+
for (rbytes = 0; rbytes < msg_ptr->length; rbytes += n)
205+
if ((n = recv(sock, (char *)msg_ptr->buffer + rbytes, msg_ptr->length - rbytes, 0)) <= 0)
206+
err_sys("Recevier Buffer Error");
207+
208+
return msg_ptr->length;
209+
}
210+
211+
/* msg_send returns the length of bytes in msg_ptr->buffer,which have been sent out successfully
212+
*/
213+
int TcpClient::msg_send(int sock, Msg* msg_ptr)
214+
{
215+
int n;
216+
if ((n = send(sock, (char *)msg_ptr,MSGHDRSIZE + msg_ptr->length, 0)) != (MSGHDRSIZE + msg_ptr->length))
217+
err_sys("Send MSGHDRSIZE+length Error");
218+
return (n - MSGHDRSIZE);
219+
}
220+
221+
int main(int argc, char* argv[])
222+
{
223+
TcpClient* tc = new TcpClient();
224+
tc->run();
225+
system("pause");
226+
return 0;
227+
}

readme.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# HTTP Web Server in C++
2+
3+
* HTTP web server that supports get request
4+
* Using Pure C++ sockets
5+
6+
-----
7+
## It's an incomplete project, just supports the get request

serv/Thread.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include <stdio.h>
2+
#include "Thread.h"
3+
4+
/*
5+
* This is the callback needed by the Thread class
6+
*/
7+
void * Thread::pthread_callback(void * ptrThis)
8+
{
9+
10+
if (ptrThis == NULL)
11+
return NULL;
12+
Thread * ptr_this = (Thread *)(ptrThis);
13+
ptr_this->run();
14+
return NULL;
15+
}
16+
17+
void Thread::start()
18+
{
19+
int result;
20+
if ((result = _beginthread((void(*)(void *))Thread::pthread_callback, STKSIZE, this)) < 0)
21+
{
22+
printf("_beginthread error\n");
23+
exit(-1);
24+
}
25+
26+
27+
}
28+
29+
30+

serv/Thread.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
#ifndef THREAD_HPP
3+
#define THREAD_HPP
4+
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <process.h>
8+
9+
#define STKSIZE 16536
10+
class Thread {
11+
public:
12+
13+
Thread()
14+
{}
15+
virtual ~Thread()
16+
{}
17+
18+
static void * pthread_callback(void * ptrThis);
19+
20+
virtual void run() = 0;
21+
void start();
22+
};
23+
#endif

0 commit comments

Comments
 (0)