I make server in c by socket. Client send request to server. Server parse it and send back data (html,png,jpg or bash script output). I have some questions about it.
When I read html file and send it to client. If file is large data are not send and browser reset connection The connection was reset How can i wait until all data are send? in this loop.
while ((ret = read(html, buff, 1023)) > 0)
{
write(client_socketfd, buff, ret);
}
Is it possible to send image(png or jpg) same way like html, only change Content type in html header?
How it works if in html file are a tags with src="another.html" after click on it client send GET request?
How it works if in html file are img tags?
Last question what is the best way to close infinity loop server. In linux if I close it with CTRL C socket are not close.
If something else is wrong I will be grateful for your advice.
int main(int argc, char *argv[])
{
int result;
int socket_desc, client_socketfd, c, read_size, buffer = 0;
struct sockaddr_in server, client;
char sprava[256];
int arg;
int port = 0;
char *homeDir = NULL;
//get command line arguments -p port -d home dir
while ((arg = getopt(argc, argv, "p:d:")) != -1) {
switch (arg) {
case 'p':
port = atoi(optarg);
break;
case 'd':
homeDir = optarg;
break;
default:
fprintf(stderr, "Please speicify -p port and -d home directiory\n");
exit(1);
}
}
if (port < 1500 || homeDir == NULL) {
fprintf(stderr, "BAD arguments use: -p port(greather then 1500) -d home dir\n");
exit(1);
}
//Create socket
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1)
{
printf("Could not create socket");
return 1;
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
//Bind
if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0)
{
fprintf(stderr, "bind failed\n");
exit(1);
}
printf("bind done\n");
//Listen max 3
listen(socket_desc, 3);
//Accept and incoming connection
int loop = 1;
while (loop) {
printf("Waiting for incoming connections...\n");
c = sizeof(struct sockaddr_in);
loop = 0; //only for testing, if everything run ok loop will be infinity
client_socketfd = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
if (client_socketfd < 0) {
fprintf(stderr, "Accept failed\n");
exit(1);
}
//In child proc we are sending data
if (fork() == 0) {
close(socket_desc);//we dont need desc in child
bzero(sprava, 256);//all on '\0'
result = read(client_socketfd, sprava, 255);
printf("Server read: %s\n", sprava);
char* path;
int kod = parser(sprava, &path);//in path is path to file
if (kod == ERROR_FILE_TYPE)
{
printf("BAD request!!!!\n");
shutdown(client_socketfd, SHUT_RDWR);
close(client_socketfd);
}
if (kod == HTML || kod == BASH || kod == JPG || kod == PNG)
{
if (kod == BASH)
{
FILE *pipe;
char *cmd = path;
strcat(cmd, " 2>&1");//error output send to pipe
printf("New command is=%s\n", cmd + 1);//we dont need first /
//open pipe without first /
pipe = popen(cmd + 1, "r");
if (pipe != NULL) {
char text[1035];
while (fgets(text, sizeof(text) - 1, pipe) != NULL) {
printf("output=%s", path);
write(client_socketfd, text, strlen(text));
}
}
pclose(pipe);
}
else if (kod == HTML)
{
int html;
long len;
char buff[1024] = { 0 };
int ret;
printf("Try to open file=%s\n", path + 1);
html = open(path + 1, O_RDONLY);
if (html == -1) {
fprintf(stderr, "Error opening file\n");
}
len = (long)lseek(html, (off_t)0, SEEK_END);//len of file
lseek(html, (off_t)0, SEEK_SET);
sprintf(buff, "HTTP/1.1 200 OK\nServer: nweb/%d.0\nContent-Length: %ld\nConnection: close\nContent-Type: %s\n\n", 20, len, "text/html");
//send html header to client
printf("Length of file=%d\n", len);
write(client_socketfd, buff, strlen(buff));
printf("Header was send\n");
while ((ret = read(html, buff, 1023)) > 0)
{
printf("number of bytes read=%d\n", ret);
//write data to client,it will make connection reset
write(client_socketfd, buff, ret);
}
}
free(path);
}
shutdown(client_socketfd, SHUT_RDWR);
close(client_socketfd);
exit(0);
}
//in parent close client
else {
close(client_socketfd);
wait(&wt);//this wait is only for testing
}
}
close(socket_desc);
return 0;
}
read()ing from a socket does not necessarily return as much bytes as requested, but few. The numbers of reads does not need to match to the number of writes. Read the documentation closely.int c; ... ... (socklen_t*) &c);, but justsocklen_t c; ... ... &c);. Imaging what would happen ifintwould be of different size thensocklen_t.