i need to transfer a file of 8.3MB over TCP, when i use file pointers to read and write to files then i send about 8.6MB data and also receives 8.6 MB of data by calculating the output of send and recv calls although my file size is 8.3 MB, further the when i check the size of file separately by seeing its properties then it is around 3-5 MB (varies on every transfer) but when i use file descriptors in place of file pointers then i send and recv exactly 8.3 MB of data and file property size also shows 8.3 MB. So what is the problem in using file pointers and why is it removed in case of file descriptors.... but if i use file descriptors then i am not able to read the text file that i sent. Text editors shows some binary data in the file. i am not getting a bit of what is happening... please help and thanks in advance
server.cpp
#include "server.h"
void server()
{
int fd = open("out.txt",O_WRONLY);
struct sockaddr_in sin;
socklen_t addr_size;
char buf[MAX_LINE];
int len;
int s, new_s;
/* build address data structure */
bzero((char *) & sin, sizeof (sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
printf("File Descriptor : %d", fd);
/* setup passive open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("simplex-talk: socket");
exit(1);
}
if ((bind(s, (struct sockaddr *) & sin, sizeof (sin))) < 0)
{
perror("simplex-talk: bind");
exit(1);
}
listen(s, MAX_PENDING);
// wait for connection, then receive and print text */
while (1)
{
if ((new_s = accept(s, (struct sockaddr *) & sin, &addr_size)) < 0)
{
perror("simplex-talk: accept");
exit(1);
}
float total = 0;
printf("File Descriptor : %d", fd);
while (len = recv(new_s, buf, MAX_LINE, 0) && strcmp(buf,"close"))
{
buf[len] = 0;
total = total+len;
//write(stdout, buf, len);
write(fd, buf, len);
//printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
}
printf("File Descriptor : %d", fd);
close(new_s);
}
}
client.cpp
#include "client.h"
void client(int argc, char** argv)
{
int fd = open("/home/nikku/Desktop/data.txt",O_RDONLY);
if (fd < 0 ) perror("File not opened\n");
struct hostent *hp;
struct sockaddr_in sin;
char *host;
char buf[MAX_LINE];
int s;
int len;
host = argv[1];
if (argc == 2)
{
host = argv[1];
}
else
{
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
/* translate host name into peer’s IP address */
gethostname(host,20);
printf("%s\n",host);
hp = gethostbyname(host);
if (!hp)
{
fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
exit(1);
}
/* build address data structure */
bzero((char *) & sin, sizeof (sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, (char *) & sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
/* active open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("simp开发者_如何学Pythonlex-talk: socket");
exit(1);
}
if (connect(s, (struct sockaddr *) & sin, sizeof (sin)) < 0)
{
perror("simplex-talk: connect");
close(s);
exit(1);
}
printf("Connection Succeeded\n");
/* main loop: get and send lines of text */
float total = 0;
while (read(fd, buf, MAX_LINE))
{
//usleep(1000);;
len = strlen(buf) + 1;
total += send(s, buf, len, 0);
//printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
}
send(s, "close", 6, 0);
close(fd);
}
Just if i replace use of file descriptors with pointers and use fgets and fputs to read and write then my file transfer does not take properly. But if i use file descriptors then i am not able to read the text file that i sent. Text editors shows some binary data in the file.
while (read(fd, buf, MAX_LINE))
{
//usleep(1000);;
len = strlen(buf) + 1;
total += send(s, buf, len, 0);
//printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
}
There is an issue here, you have no guarantee that read
will read a zero byte so strlen(buf)
is potentially dangerous. Also note, that as you set len
to strlen(buf) + 1
, if you do encouter a zero byte you will send it across the socket but if you don't read a zero byte, strlen
will read beyond the end of the array and send 'junk' across the socket.
It would be sensible to store the return value of read
so that you know how many bytes were actually read from fd
.
while (len = recv(new_s, buf, MAX_LINE, 0) && strcmp(buf,"close"))
{
buf[len] = 0;
total = total+len;
//write(stdout, buf, len);
write(fd, buf, len);
//printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
}
Your receive side seems to assume that each call to recv won't include a zero byte as you manually terminate the buffer with a 0. Note that you don't actually have room to do this if recv
actually receives MAX_LINE
bytes as buf
only consists of MAX_LINE
elements. As your write is restricted by length in any case, there is no need to do buf[len] = 0;
.
精彩评论