I'm attempting to use a simple HTTP server written in C that makes use of UNIX BSD sockets. I've got it working somewhat but am having the following issues.
1, The server only prints "hello world!" on linux browsers and not on windows browsers, ie, I can make use of chrome / firefox on linux and see the text in the browser but not on a windows machine in the same browsers.
2, Rather then sending "hello world" with all of the response headers and closing the connection like a normal web page, what I'm seeing is that when I test the server page(localhost:xxxx) I am presented with the text and http responses in the code but the page is in a continuous load(Tab keeps spinning). Then the moment I turn the server off the page returns "failed to connect to server)
My question is, given the below code, why does this not display out to browsers on windows and why does it not close the connection whilst leaving the client with the information sent?
This uses simple BSD sockets.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> //definitions for system variables
#include <sys/socket.h> //definitions / structures for sockets
#include <netinet/in.h> //const's and structures used by internet domain
void error(const char *msg) //takes litteral msg passed in and prints, then exits.
{
perror(msg); //man perror
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, // socket file descriptor 1. both return values from system
newsockfd, // socket file descriptor 2
portno; // port number to associate with this socket
socklen_t clilen; //stored address size of each client
char buffer[256]; //stores chars from socket buffer
struct sockaddr_in serv_addr, cli_addr;
/*sockaddr_in, structure containing an internet address. most of the magic DEFINED BELOW
struct sockaddr_in
{
short sin_family; /* must be AF_INET
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8]; /* Not used, must be zero
};
*/
int n; //stores return values of read() / write() system calls)
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
} //self explanitory
/*socket() creates a new socket and takes 3 arguments, the first being the address domain of the socket
* Sockets in this case can use two types of domains which are both system constants
* AF_UNIX - Used for parent child prc's on the same machine
* AF_INET - Used for host to host communication, Ie internet communication
*
* The second option SOCKET_STREAM is the type of stream/communication used in the socket. ie TCP/UDP, Being
* SOCK_STREAM - TCP - A continuous stream/connection during the life span of the sockets communication
* SOCK_DGRAM - UDP - A connectionless strea/connection which uses less resources/is faster but possible byte loss
*
* The third option is the protocol used, due to specifying the type of stream this is almost always left to 0
* Leaving the arg at 0 implies that the operating system will make the best call and due to setting the stream it will
* more then likely choose to use the requested method
*
* This socket() in general returns a value for the subsequent descriptor for reference. If on failure, the socket()
* will return -1 and fail hence if(sockfd<0){}
*
* man socket() for information Andrew,
*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
/*bzero() sets all values in buffer to 0(00000000)*/
bzero(
(char *) &serv_addr,
sizeof(serv_addr)
); //Deref &serv_addr, and ensures to 0 out all bytes in buffer(entire struct)
portno = atoi(argv[1]);//port number to be used for communication,
serv_addr.sin_family = AF_INET; //set to internet. sin_family is stored in sockadr_in structure
serv_addr.sin_addr.s_addr = INADDR_ANY; //structure in structure. s_addr holds the host address. IN_ADDR is always the systems ip
serv_addr.sin_port = htons(portno); //convert to network byte order. Holds th eport number, places into readable format
/*
* checks and binds to new file descripter, socketaddr(deref) and allocates the size of the address bound to.
* If less then zero. it will fail(-1)
*/
if (bind(sockfd,
(struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5); // listens on bound socket/descriptor and allows up to 5 connections to be waiting in queue(max allowed on system
clilen = sizeof(cli_addr); // assigns value based on size of bytes in clients address
newsockfd = accept(sockfd, // new descripter to use when accepting a client
(struct sockaddr *) &cli_addr, //gathers client connection information for arg(deref)
&clilen); // Passes in clilen, for lenght of client address. not a copy, the real shiz
if (newsockfd < 0)
error("ERROR on accept"); // again, don't be a fucking dick.
bzero(buffer,256); // ensure buffer is not tampered at this point or gross
n = read(newsockfd,buffer,255); // use sys-call read() to store data in buffer from client. use 255bytes or client input
// which ever is less.
if (n < 0) error("ERROR reading from socket"); // if failed as fuck, let's cry
n = write(newsockfd,"HTTP/1.0 200 OK\n",16); // Write back to client. to bound socket from client. they see this shit.
n = write(newsockfd,"Connection: Keep-alive\n",23);
n = write(newsockfd,"Connection: close\n",18);
n = write(newsockfd,"Content-type: text/html; charset=UTF-8\n",39);
n = write(newsockfd,"\n",1);
n = write(newsockfd,"<!DOCTYPE HTML>\n<html><head><title>Hello World!</title></head>\n",62);
n = write(newsockfd,"<body><h1>Hello World!</h1>\n",28);
n = write(newsockfd,"</body></html>\n",15);
if (n < 0) error("ERROR writing to socket"); // duh
// cleaning up...
//close(newsockfd);
// close(sockfd);
getchar();
return 0;
}
Aucun commentaire:
Enregistrer un commentaire