I am implenting multi-threaded web-server I initially tested for single connection without threads and I could decode request and send the file .All html pages are correctly displayed but browser says gif is corrupted.The send API returns the same no of bytes that I sent.
The send function works for html but sends corrupt images for gif.The send API does return the same bytes that i send so why is the image corrupted.The mode i believe is binary for reading the file.Its ubuntu 12.04 x86 g++/gcc 4.7.2
Plz identify the problem if possible.
#include <iostream>
#include <list>
#include "network.h"
#include <pthread.h>
#include <fstream>
#include <ctype.h>
#include <inttypes.h>
#include "http.h"
#include <string>
using namespace std;
int sockfd;
int i;
char dir[2000];
pthread_mutex_t elock;
pthread_cond_t cwait;
pthread_mutex_t llock;
class clist
{
public:
int sock;
bool req;
char ext[200];
char path[2000];
int fsize;
} obj;
list <clist> cl;
list<clist>::iterator it;
bool compare(const clist& lhs, const clist& rhs)
{
return lhs.fsize < rhs.fsize;
}
void tok_req(char *);
void get_size();
void process_req(clist *);
pthread_t td;
void * exect(void*)
{
while(1)
{
pthread_mutex_lock(&llock);
if (cl.empty())
{
pthread_cond_wait(&cwait,&llock);
}
clist *obj1;
*obj1=cl.front();
process_req(obj1);
free(obj1);
pthread_cond_signal(&cwait);
pthread_mutex_unlock(&llock);
}
return NULL;
}
void * sched(void*)
{
sleep(20);
while(1)
{
pthread_mutex_lock(&llock);
if (cl.empty())
{
pthread_cond_wait(&cwait,&llock);
}
cl.sort(compare);
it=cl.begin();
for(; it!=cl.end(); it++)
{
cout<<it->sock<<" ";
cout<<it->req<<" ";
cout<<it->path<<" ";
cout<<it->ext<<" ";
cout<<it->fsize<<endl;
}
pthread_cond_signal(&cwait);
pthread_mutex_unlock(&llock);
}
return NULL;
}
int main(int argc,char *argv[])
{
n=atoi(argv[1]);
pthread_t sid;
int const tno=n;
pthread_t tid[tno];
for (i=0; i<n; i++)
{
pthread_create(&tid[i],NULL,&exect,NULL);
}
pthread_create(&sid,NULL,&sched,NULL);
servcl_memset();
sock_create();
sock_bind();
set_listen();
char buf[1024];
while(1)
{
cout<<"Hello"<<endl;
strcpy(dir,"");
strcpy(dir,argv[2]);
sockfd=accept(listen_sd,(sockaddr *)&remoteaddr,&addrlen);
pthread_mutex_lock(&llock);
obj.sock=sockfd;
if (sockfd == -1)
perror("accept");
memset(buf,0,sizeof buf);
recv(sockfd,buf,sizeof buf,0);
tok_req(buf);
get_size();
cl.push_back(obj);
pthread_mutex_unlock(&llock);
}
close(sockfd);
close(listen_sd); return 0;
}
void tok_req(char *s)
{
char *p1;
char *p2;
p1=strtok(s," ");
if (strcasecmp(p1,"GET")==0)
obj.req=0;
if (strcasecmp(p1,"HEAD")==0)
obj.req=1;
p1=strtok(NULL," ");
strcpy(obj.path,p1);
strcat(dir,obj.path);
strcpy(obj.path,dir);
p2=strtok(p1,".");
p2=strtok(NULL,".");
strcpy(obj.ext,p2);
}
void get_size()
{
ifstream h;
h.open(obj.path,ios_base::in|ios::binary);
h.seekg(0,ios::end);
obj.fsize=h.tellg();
h.close();
}
void process_req(clist *obj)
{
char buf[obj->fsize];
ifstream h;
h.open(obj->path,ios::binary|ios_base::in);
if ( (strcmp(obj->ext,"html") ==0) || (strcmp(obj->ext,"htm")==0) )
{
send(obj->sock,TXT,sizeof TXT,0);
h.read(buf,obj->fsize);
h.close();
send(obj->sock,buf,obj->fsize,0);
close(obj->sock);
return;
}
else
{
memset(buf,0,sizeof buf);
h.read(buf,obj->fsize);
h.close();
send(obj->sock,GIF,sizeof GIF,0);
send(obj->sock,buf,obj->fsize,0);
close(sockfd);
return;
}
}
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET)
{
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
unsigned int get_in_port(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET)
{
return (((struct sockaddr_in*)sa)->sin_port);
}
return (((struct sockaddr_in6*)sa)->sin6_port);
}
void servcl_memset()
{
memset(&hints, 0, sizeof(hints));
hints.ai_family= AF_INET;
hints.ai_socktype=SOCK_STREAM;
hints.ai_flags=AI_PASSIVE;
}
void sock_create()
{
if ((info = getaddrinfo(NULL, PORT, &hints, &loadinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(info));
return;
}
if ((listen_sd = socket(loadinfo->ai_family, loadinfo->ai_socktype,loadinfo->ai_protocol)) == -1) {
perror("server: socket");
return;
}
info = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR,&yes, sizeof(int));
if (info < 0)
{
perror("setsockopt() failed");
close(listen_sd);
return;
}
}
void sock_bind()
{
info= bind(listen_sd,loadinfo->ai_addr,loadinfo->ai_addrlen);
if (info < 0)
{
perror("bind() failed");
close(listen_sd);
return;
}
}
void set_listen()
{
info = listen(listen_sd, n);
if (info < 0)
{
perror("listen() failed");
close(listen_sd);
exit(-1);
}
}