2012-05-20 99 views
0

嗨,我写了一个服务器应用程序,它接受通常是文件名的客户端的名称。它打开文件,将内容读入缓冲区,然后使用send()通过以太网传输缓冲区。但问题出现在所有字节都没有被成功接收的客户端。我只收到我发送的一部分内容。如何使用套接字apis发送和接收字节?

供您参考,下面是服务器端的代码片段:

服务器

fp = fopen(filename,"r+"); 
     strcpy(str,""); 
     fseek(fp, 0L, SEEK_END); 
     size = ftell(fp); 
     fseek(fp, 0L, SEEK_SET); 
     fread(str, size, 1,fp); 
     fclose(fp); 
     printf("Size of the file is : %d\n",size); 
     sprintf(filename, "%d", size); 
     n = send(nsd, filename, strlen(filename), 0); 

while(size > 0){ 
      n = send(nsd, str, strlen(str), 0); 
      printf("%d bytes sent successfully\n",n);   
      if(n == 0) break; 
      sentbytes = sentbytes + n; 
      size = size - sentbytes; 
     } 

请帮我写客户端app.I我目前困惑如何去写它。我是否将recv()部分放在while(1)循环中,以便客户端继续运行,直到所有字节都已成功接收为止?

+0

你用什么样的插座?它是一个UDP套接字?如果是这种情况,你应该迎合丢包和转发...或者,你可以去TCP ... – user1055604

+0

这是我使用的TCP套接字... – phoenix

回答

3

EDITED
对于初学者来说,你可以在同一时间既块和read from the filewrite to the socket
因为您正在通过TCP传输数据,所以请记住,数据作为流可靠传输,而不是作为消息传输。因此,除了订单外,不要对数据如何被收回做出假设。

这里是如何可以写成:

open socket 
open file 
size_of_file = read_file_size(file); 
send(socket, &size_of_file, sizeof(int), ...) 
while (all is written) 
    read fixed chunk from file 
    write as much was read to the socket 
cleanup // close file, socket 

至于recv的一部分,我认为这是最好的,你发送的文件大小比为整数,并保持在读一while循环,直到您已经收到了从服务器发送的尽可能多的字节数。

是这样的:

recv(socket, &size_of_msg, sizeof(int), ...) 
while(all is read) 
    read fixed chunk from the socket 
cleanup 
2

“我应该在一个while(1)循环中放置recv()部分,以便客户端继续运行,直到所有字节都被成功接收为止?”

就是这样的。永远不要假定recv()调用获得了所有发送的内容 - tcp/ip将消息分解为较低级别的数据包,recv()将在读取任何点上实际接收到的任何数据量后返回。您不必直接担心,除非您确实需要使用某种协议来指示消息的长度,因此接收方知道要读多少,然后例如:

char buffer[4096]; 
int msgsz = 600, // see below 
    sofar = 0, 
    cur; 

while (sofar < msgsz) { 
    cur = recv (
     socket_fd, 
     &buffer[sofar], 
     msgsz - sofar, 
     0 
    ); 
    if (cur == -1) { 
     // error 
     break; 
    } else if (cur == 0) { 
     // disconnected 
     break; 
    } 
    sofar += cur; 
} 

WRT msgsz,你可以将它包含在固定长度的头文件中,这是首先读取的。一个简单的版本可能只是4个字节,包含一个uint32_t,即一个int长度。您也可以使用以空字符结尾的字符串和一个数字,但这意味着直到找到'\0'

2

使用strlen似乎并不合适。你已经读过这个文件,你知道它有多长,为什么strlen?要么你会得到相同的结果(所以它是多余的),否则你会得到其他东西(所以这是一个错误)。

3

那么我看到至少有一些问题,你通过套接字发送消息的方式。

从FREAD的手册页第一:

The function fread() reads nmemb elements of data, each size bytes 
    long, from the stream pointed to by stream, storing them at the loca- 
    tion given by ptr. 

和你正在尝试是这样的:

fread(str, size, 1,fp); 

我假设你的意思是

fread(str, 1,size,fp); 

虽然shold不是问题。

但问题就出在这里:

n = send(nsd, str, strlen(str), 0); 
     printf("%d bytes sent successfully\n",n);   
     if(n == 0) break; 
     sentbytes = sentbytes + n; 
     size = size - sentbytes; 

虽然你会减少“大小”由字节数减少发送成功,你在哪里延伸STR指向新缓冲区的位置,其中的数据将被发送。这将只会重复发送缓冲区的初始字节。

 str += n; //Assuming str is char* 

将解决您的问题。

相关问题