when reading the file data into file_buff and then using send() to send the data out to the browser I get weird data like this->(ÿØÿà�JFIF�) instead of the image that is supposed to show up. I can send data like text out to the browser but can't seem to send the image data out.
void *connectionThread(void *socket_desc){
char buffer[100000];
int newsockfd = *(int*)socket_desc;
int n;
magic_t myt = magic_open(MAGIC_ERROR|MAGIC_MIME_TYPE);
magic_load(myt,NULL);
char file_buff [800000];
struct stat filestat;
bzero(buffer,256);
FILE * fp;
while (1)
{memset(buffer, 0, 100000);n = read(newsockfd,buffer,100000);
if (n < 0) error("ERROR reading from socket");
printf("it is something here: %s",buffer);
char *token = strtok(buffer," ");
if(token !=NULL)
token = strtok(NULL, " ");
token = strtok(token,"\n");
token = strtok(token,"/");
fp = fopen ("Koala.jpg", "rb");
write(newsockfd,"Content-Length: 780831\r\n",strlen("Content-Length: 780831\n"));
write(newsockfd,"Content-Type: ",strlen("Content-type: "));
write(newsockfd,magic_file(myt,token),strlen(magic_file(myt,token))); //get Content-type
write(newsockfd,"\n\n",strlen("\n\n"));
//knowing the size of image is 780831
fread(file_buff, sizeof(char), 780831 + 1, fp);
fclose(fp);
send(newsockfd, file_buff, 780831,0);
if ((strncmp(buffer,"quit",4) == 0)) //quit
break;
n = write(newsockfd,"I got your message\n May I have another\n",40);
if (n < 0) error("ERROR writing to socket");
write(newsockfd,"Ok, I am quitting\n",18);
}
close(newsockfd);
magic_close(myt);
pthread_exit(NULL);
return 0;
}
You have to changes the header that you are sending. Set you content-type as Multi-part data.
HTTP/1.1 200 OK\r\ncontent-type: multipart\r\ncontent-length:%ld\r\nConnnection: Close;
I think this should solve your problem.
Related
In here I am sending file name first then sending the file in chunks, then trying to read the received message but it is just freezing. No respond. But after loop if I shutdown the WR shutdown(connfd,SHUT_WR); It is working fine. Though I should be able to send message again, if I do this I can not do that.
CLIENT.C
write(sockfd, fname,100);
FILE *fp = fopen(fname,"rb");
if(fp==NULL)
{
printf("File opern error");
exit(1);
}
int hi = 0;
while(1)
{
/* First read file in chunks of 256 bytes */
unsigned char buff[1024]={0};
int nread = fread(buff,1,1024,fp);
/* If read was success, send data. */
if(nread > 0)
{
hi++;
//printf("Sending \n");
write(sockfd, buff, nread);
}
if (nread < 1024)
{
if (feof(fp))
{
printf("File transfer completed!\n");
}
if (ferror(fp))
printf("Error reading\n");
break;
}
}
char fname2[100];
// cant read
read(sockfd, fname2, 100);
printf("File Name: %s\n",fname2);
SERVER.C
FILE *fp;
int bytesReceived = 0;
char recvBuff[1024];
char fname[100];
char fname2[100];
read(newsockfd, fname, 100);
//strcat(fname,"AK");
printf("File Name: %s\n",fname);
printf("Receiving file...");
fp = fopen(fname, "ab");
if(NULL == fp)
{
printf("Error opening file");
}
long double sz=1;
/* Receive data in chunks of 256 bytes */
printf("\nCompleted.\n");
int hi = 0;
while((bytesReceived = read(newsockfd, recvBuff, 1024)) > 0)
{
hi++;
sz++;
fwrite(recvBuff, 1,bytesReceived,fp);
}
printf("Not pring this this!");
if(bytesReceived < 0)
{
printf("\n Read Error \n");
}
write(newsockfd, "SayGee",100);
I had to send the size of the file, then check from the other side inside loop. It was in deadlock.I found the solution. So thanks anyway!
I want to be able to send a file from the client to the server. I'm using TCP. I'm trying to use fseek and etc to get the size of the file because I want to be able to handle large files, and then send that amount of bytes of data as well as the files contents to the server. So far, according to my printf messages everything goes through and the file is created. However, the file created on the server is empty. There's obviously something wrong with the way I am sending it and receiving it via parameters or something, but I can't figure it out. Can someone please show me where I've gone wrong and how I can fix it because I'm so close!
Server part:
if(getFile){
char *tmp = buf + 9;
char filename2[MAX_BLOCK_SIZE];
int length, x;
long file_size = 0;
FILE *fp;
strcpy(filename2, tmp);
printf("Server receiving file name...\n");
//first 'read' receives the file name
fp = fopen(filename2, "wb");
if(fp == NULL){
printf("File could not be opened.\n");
exit(1);
}
printf("Server receiving file...\n");
while((x = read(sd, buf, sizeof(buf)) > 0)){ //second read now retrieving the file
printf("Server creating new file...\n");
fwrite(buf, 1, file_size, fp);
}
fclose(fp);
printf("The server has received the requested document.\n");
}
Client side:
else if(putCommand){
char *tmp = buf + 4;
char filename[MAX_BLOCK_SIZE];
long file_size;
strcpy(filename, "filename ");
strcat(filename, tmp);
FILE *fp;
printf("File name: %s\n", tmp);
fp = fopen(tmp, "rb");
if(fp == NULL){
printf("ERROR: Requested file does not exist.\n");
}
else{
printf("Client sending filename...\n");
if ((nw = write(sd, filename, sizeof(filename)) < nr)){ //sending the file name to the client first
printf("Error sending client's filename.\n");
}
//size_t file_size;
printf("Client sending file...\n");
fseek(fp, 0, SEEK_END);
long filesize = ftell(fp);
fseek(fp, 0, SEEK_SET);
while((file_size = fread(buf, 1, MAX_BLOCK_SIZE, fp)) > 0){ //sending the file
if ((x = write(sd, buf, filesize) < 0)){
printf("Error sending client file.\n");
}
}
fclose(fp);
}
It is close to a typo. On the receiver side, you have:
long file_size = 0;
...
while(...)
...
fwrite(buf, 1, file_size, fp);
So you consistently write 0 byte.
The standard way is:
while((x = read(sd, buf, sizeof(buf)) > 0)){ //second read now retrieving the file
printf("Server creating new file...\n");
fwrite(buf, 1, x, fp); // write the number of bytes returned by previous read
}
Last remark, I hope that buf is a true array and not a pointer...
I'm learning the socket programming and trying to write a simple http server with c. My program can load html/css/javascript files correctly, but the image files can't be loaded. For example, the website icon favicon.ico and <img> of the html file always failed to load. I'm using the code as below to build my simple server:
server.c:
#define CYAN(format, ...) \
printf("\033[1;36m" format "\33[0m\n", ## __VA_ARGS__)
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
socklen_t c_addr_size;
int s_sock;// server socket
int c_sock;// clinet socket
char buf[4096];// user agent
char msg[4096];// file content
char head[1024];// http header
char file[128];// which file requested
void init_server();
void read_request();
void send_file();
int main()
{
init_server();
while (1) {
c_sock = accept(s_sock, NULL, NULL);
if (c_sock != -1) {
int nread = recv(c_sock, buf, sizeof(buf), 0);
read_request();// TODO
CYAN("%d", nread);
CYAN("%s", buf);
send_file();
close(c_sock);
}
}
close(s_sock);
return 0;
}
void init_server()
{
s_sock = socket(AF_INET, SOCK_STREAM, 0);
assert(s_sock != -1);
s_addr.sin_family = AF_INET;
s_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
s_addr.sin_port = htons(8000);
int res = bind(s_sock, (struct sockaddr*)&s_addr, sizeof(s_addr));
if (res == -1) { perror("cannot bind"); exit(-1); }
listen(s_sock, 10);// TODO
c_addr_size = sizeof(c_addr);
}
void read_request()
{
int buf_len = strlen(buf);
int i = 0, j = 0;
for (i = 0; i < buf_len - 10; i ++) {
if (buf[i] == 'G' && buf[i + 1] == 'E' && buf[i + 2] == 'T') {// `GET` keyword
i = i + 4;// skip space
while (buf[i] != ' ') {
file[j] = buf[i];
j ++, i ++;
}
file[j] = '\0';
CYAN("%s", file);
return;
}
}
}
void send_file()
{
if (strcmp(file, "/") == 0) {
sprintf(file, "index.html");
is_html = 1;
} else {
sprintf(file, "%s", file + 1);// skip `/`
}
FILE *fp = fopen(file, "r");
// count file length
int file_len = 0;
while (fgets(msg, 1000, fp)) {// read by lines
file_len += strlen(msg);
}
// send http header
sprintf(head,
"HTTP/1.1 200 OK\n"
// "Content-Type: text/html\n"
"Content-Length: %d\n"
"\n", file_len
);
// send file content
CYAN("%d", fseek(fp, 0, SEEK_SET));
memset(msg, 0, sizeof(msg));
send(c_sock, head, strlen(head), 0);
while (fgets(msg, 1000, fp)) {// read by lines
send(c_sock, msg, strlen(msg), 0);
}
fclose(fp);
}
I'm not familiar with http, and I don't know whether I should change the content of the http header when sending images files. How to correct my code, can anyone help me?
FILE *fp = fopen(file, "r");
// count file length
int file_len = 0;
while (fgets(msg, 1000, fp)) {// read by lines
file_len += strlen(msg);
}
No. No. No. No. Never use text processing on binary data.
File length is easy.
FILE *fp = fopen(file, "rb");
fseek(fp, 0, SEEK_END);
long file_len = ftell(fp);
fseek(fp, 0, SEEK_SET);
Now to send it:
send_helper(c_sock, head, strlen(head), 0); /* send header */
while (file_len > 4096) {
int delta = fread(msg, 4096, 1, fp);
if (delta == 0) {
/* handle error */
fclose(fp);
/* need to refactor here; c_sock is useless and needs to be closed */
return;
}
send_helper(c_sock, msg, delta);
file_len -= delta;
}
if (file_len > 0) {
/* last chunk; fread only returns a short count on an actual error so no loop here */
int delta = fread(msg, 4096, 1, fp);
if (delta == 0) {
/* handle error */
fclose(fp);
/* need to refactor here; c_sock is useless and needs to be closed */
return;
}
send_helper(c_sock, msg, delta);
}
fclose(fp);
Unlike fread, send needs a loop to ensure all bytes are sent.
void send_helper(int c_sock, char *msg, size_t size)
{
while (size > 0)
{
ssize_t delta = sendto(c_sock, msg, size, 0);
/*
* not bothering to handle error well--
* we'll just error a few more times and drop out of loop anyway.
* You probably should come back and fix this later though
*/
if (delta <= 0) return;
size -= (size_t)delta;
msg += (size_t)delta;
}
}
I am having some trouble understanding why I am getting a segmentation fault in my homemade web server. I am trying to correctly label the content type for .html and .txt documents. I can open an .html file in my web browser just fine when my server is running. However, my server is closing on a segmentation fault when I try to open a .txt document. The code below is where I am getting the issue.
void* thread_runner(void* sockfd)
{
char buffer[256];
int n;
int sock = *(int*)sockfd;
bzero(buffer,256);
char filename[256];
bzero(filename,256);
n = read(sock,filename,255);
if (n < 0) error("ERROR reading from socket");
FILE *fp;
char file[4096];
char* word = strtok(filename, " ");
word = strtok(NULL, " ");
word++;
printf("filename = \"%s\"\n", word);
fp = fopen(word, "r");
if (fp == NULL) {
printf("file pointer is NULL\n");
return 0;
}
char string[4096];
char* extension;
bzero(string, 4096);
bzero(file, 4096);
char* word2;
word2 = strtok(word, ".");
while ((word2 = strtok(NULL, ".")) != NULL)
{
extension = word2;
}
printf("File Extension: %s\n", extension);
if (strncmp(extension, "html", 4096) == 0) {
printf("HTML FILE FOUND\n");
strcat(string, "HTTP/1.1 200 OK\nContent-Type: text/html\nContent-Length: 4096 \nConnection: keep-alive\n\n");
}
else if (strncmp(extension, "txt", 4096) == 0) {
printf("TXT FILE FOUND\n");
strcat(string, "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 4096\nConnection: keep-alive\n\n");
}
the error occurs in this loop.
I have used bzero on 'string'.
while (fgets(file, 4096, fp))
{
strcat(string, file);
}
//printf("Sending text:%s", string);
printf("The requested file was: %s.%s\n",word,extension);
n = write(sock,string,4096);
printf("file contents are %s\n", string);
fclose(fp);
if (n < 0) error("ERROR writing to socket");
if (n == 0)
{
close(sock);
}
You're writing past the end of string. string only has 4096 characters in it, but your loop tries to read the entire file into it when it keeps calling strcat() in a loop.
Instead of concatenating the entire file into a variable and then writing it all, use fread() to read the file in chunks and immediately write them to the socket. There's no need to read line by line.
size_t in;
while ((in = fread(file, 1, sizeof file, fp) > 0) {
int n = write(sock, file, in);
if (n < in) {
error("ERROR writing to socket");
}
}
close(sock);
fclose(fp);
I am doing a class project right now and it requires me to send data and image using socket. So far I have finished most of it. Data gets sent correctly, small images get sent correctly, but when it comes to large images, only half of it is shown. I checked the characters sent and all of them got sent. So I am not sure where I got wrong. This my function to handle get request. I have tested sending data and it worked, so I think most of this function works but probably just some small details I missed. Please help...thanks!
void handle_get(int sock, const char* url) {
FILE* pFILE;
int file, i;
//file = open(url, O_RDONLY);
pFILE = fopen(++url, "r");
char response_message[1024];
char buffer[1024];
char c;
char *header_type, *file_type;
long file_size;
//char *buffer;
if (pFILE == NULL){
snprintf (response_message, sizeof (response_message), not_found_response_template, url);
write (sock, response_message, strlen (response_message));
error("ERROR opening requested file");
}
file_type = strrchr (url, '.');
//return pointer to the last occurrance of '.'
if (!file_type)
file_type = "html";
else
file_type++;
if (strcasecmp (file_type, "jpg") == 0 || strcasecmp (file_type, "jpeg") == 0)
header_type = "image/jpeg";
else if (strcasecmp (file_type, "gif") == 0)
header_type = "image/gif";
else if (strcasecmp (file_type, "png") == 0)
header_type = "image/png";
else
header_type = "text/html";
snprintf (response_message, sizeof (response_message), ok_response, header_type);
write (sock, response_message, strlen (response_message));
puts(response_message);
int n = 0;
bzero(buffer, 1024);
while (n=fread(buffer, sizeof(char), 1024, pFILE)){
printf("n is %d\n", n);
send (sock, buffer, n, 0);
//write(sock, buffer, n);
bzero(buffer, 1024);
}
fclose (pFILE);
}