Here I'll outline steps to create basic web server on Linux in C/C++ using sockets.
Let's begin with list of ingredients:
1. We need to open a socket for listening purpose by calling following function:
int socket(int domain, int type, int protocol);
2. Next we need to bind the homeless socket just created to some address (port) using call to this function:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
3. The trap is set. Now wait for the game.
int listen(int sockfd, int backlog);
4. Accept a connection as it comes and receive the data:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
5. Send your response
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
6. Shutdown the connection and close the client socket
int shutdown(int sockfd, int how);
int close(int fd);
Here's the client code:
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SERVER_PORT 12345 /* arbitrary, but client and server must agree */
#define BUF_SIZE 4096 /* block transfer size */
#define QUEUE_SIZE 10
void fatal(const char *string)
{
printf("%s", string);
exit(1);
}
int main(int argc, char *argv[])
{
int s, b, l, fd, sa, bytes, on = 1;
char buf[BUF_SIZE]; /* buffer for outgoing file */
struct sockaddr_in channel; /* hold's IP address */
/* Build address structure to bind to socket. */
memset(&channel, 0, sizeof(channel)); /* zero channel */
channel.sin_family = AF_INET;
channel.sin_addr.s_addr = htonl(INADDR_ANY);
channel.sin_port = htons(SERVER_PORT);
/* Passive open. Wait for connection. */
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /* create socket */
if (s < 0) fatal("socket failed");
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
b = bind(s, (struct sockaddr *) &channel, sizeof(channel));
if (b < 0) fatal("bind failed");
l = listen(s, QUEUE_SIZE); /* specify queue size */
if (l < 0) fatal("listen failed");
/* Socket is now set up and bound. Wait for connection and process it. */
while (1) {
sa = accept(s, 0, 0); /* block for connection request */
if (sa < 0) fatal("accept failed");
read(sa, buf, BUF_SIZE); /* read file name from socket */
printf("[%s]\n", buf );
/* Get and return the file. */
fd = open(buf, O_RDONLY); /* open the file to be sent back */
if (fd < 0) fatal("open failed");
while (1) {
bytes = read(fd, buf, BUF_SIZE); /* read from file */
if (bytes <= 0) break; /* check for end of file */
write(sa, buf, bytes); /* write bytes to socket */
}
close(fd); /* close file */
close(sa); /* close connection */
}
}
Let's begin with list of ingredients:
1. We need to open a socket for listening purpose by calling following function:
int socket(int domain, int type, int protocol);
2. Next we need to bind the homeless socket just created to some address (port) using call to this function:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
3. The trap is set. Now wait for the game.
int listen(int sockfd, int backlog);
4. Accept a connection as it comes and receive the data:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
5. Send your response
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
6. Shutdown the connection and close the client socket
int shutdown(int sockfd, int how);
int close(int fd);
Here's the client code:
/* This page contains the client program. The following one contains the
* server program. Once the server has been compiled and started, clients
* anywhere on the Internet can send commands (file names) to the server.
* The server responds by opening and returning the entire file requested.
*/
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
void fatal(const char *string)
{
printf("%s\n", string);
exit(1);
}
#define SERVER_PORT 12345 /* arbitrary, but client and server must agree */
#define BUF_SIZE 4096 /* block transfer size */
int main(int argc, char **argv)
{
int c, s, bytes;
char buf[BUF_SIZE]; /* buffer for incoming file */
struct sockaddr_in channel; /* holds IP address */
if (argc != 2) fatal("Usage: client file-name");
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s < 0) fatal("socket");
memset(&channel, 0, sizeof(channel));
channel.sin_family= AF_INET;
inet_pton ( AF_INET, "localhost", &channel.sin_addr );
channel.sin_port= htons(SERVER_PORT);
c = connect(s, (struct sockaddr *) &channel, sizeof(channel));
if (c < 0) fatal("connect failed");
/* Connection is now established. Send file name including 0 byte at end. */
write(s, argv[1], strlen(argv[1])+1);
/* Go get the file and write it to standard output. */
while (1) {
bytes = read(s, buf, BUF_SIZE); /* read from socket */
if (bytes <= 0) exit(0); /* check for end of file */
write(1, buf, bytes); /* write to standard output */
}
}
And the server code: #include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SERVER_PORT 12345 /* arbitrary, but client and server must agree */
#define BUF_SIZE 4096 /* block transfer size */
#define QUEUE_SIZE 10
void fatal(const char *string)
{
printf("%s", string);
exit(1);
}
int main(int argc, char *argv[])
{
int s, b, l, fd, sa, bytes, on = 1;
char buf[BUF_SIZE]; /* buffer for outgoing file */
struct sockaddr_in channel; /* hold's IP address */
/* Build address structure to bind to socket. */
memset(&channel, 0, sizeof(channel)); /* zero channel */
channel.sin_family = AF_INET;
channel.sin_addr.s_addr = htonl(INADDR_ANY);
channel.sin_port = htons(SERVER_PORT);
/* Passive open. Wait for connection. */
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /* create socket */
if (s < 0) fatal("socket failed");
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
b = bind(s, (struct sockaddr *) &channel, sizeof(channel));
if (b < 0) fatal("bind failed");
l = listen(s, QUEUE_SIZE); /* specify queue size */
if (l < 0) fatal("listen failed");
/* Socket is now set up and bound. Wait for connection and process it. */
while (1) {
sa = accept(s, 0, 0); /* block for connection request */
if (sa < 0) fatal("accept failed");
read(sa, buf, BUF_SIZE); /* read file name from socket */
printf("[%s]\n", buf );
/* Get and return the file. */
fd = open(buf, O_RDONLY); /* open the file to be sent back */
if (fd < 0) fatal("open failed");
while (1) {
bytes = read(fd, buf, BUF_SIZE); /* read from file */
if (bytes <= 0) break; /* check for end of file */
write(sa, buf, bytes); /* write bytes to socket */
}
close(fd); /* close file */
close(sa); /* close connection */
}
}
Based on Tanenbaum, "Computer Networks"
No comments:
Post a Comment