免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 6805 | 回复: 26
打印 上一主题 下一主题

关于socket 传送文件的问题 [困惑] [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-11-19 21:53 |只看该作者 |正序浏览
关于socket 传送文件的问题 [困惑]

这几天一直被这个问题困扰着

编写了一个socket 传送BMP 图像的程序

client 向 server 传送client.bmp

但是在server 端接受到的图像不能打开

用 UltraEdit  打开client发送的 client.bmp图像和server接受的图像  server.bmp 对比,

server.bmp文件的前面 1448个字节 与 client.bmp的前1448个字节一样

但是server.bmp文件第1448个字节后的全部字节都为 0x00了

所以 server.bmp 所显示出来的几乎就是黑色的图片了

我的问题是 ---》 传送的是非0值,为什么收了一部分后就全变为0了呢?

请大虾们指点一下,我参考了资料+百度这个问题,还是百思不得其解。


我把我的代码附上

  1. ----------server-----------
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <errno.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <netinet/in.h>

  10. #define SERVPORT 3333
  11. #define BACKLOG 10
  12. #define MAX_CONNECTED_NO 10
  13. #define MAXDATASIZE 100*100*3+54

  14. int main()
  15. {
  16.          struct sockaddr_in  server_sockaddr,client_sockaddr;
  17.          int sin_size,recvbytes;
  18.          int sockfd,client_fd;
  19.          char buf[MAXDATASIZE];
  20.          int nwrite,i;
  21.        
  22.          FILE *fbmp;
  23.          char bmpdata[100*100*3+54];       
  24.        
  25.         if (( fbmp = fopen("server.bmp", "w+")) == NULL)
  26.                    {
  27.                    printf("Open  server bmp error !\n");
  28.                    exit(-1);
  29.             }

  30.          
  31.          if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
  32.                    perror("socket");
  33.                    exit(1);
  34.          }

  35.    printf("socket success!,sockfd = %d\n",sockfd);
  36.    
  37.    server_sockaddr.sin_family = AF_INET;         
  38.    server_sockaddr.sin_port = htons(SERVPORT);                 
  39.    server_sockaddr.sin_addr.s_addr = INADDR_ANY;
  40.    
  41.    bzero(&(server_sockaddr.sin_zero), 8);
  42.    
  43.    if(bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr)) == -1 ){
  44.        perror("bind");
  45.        exit(1);           
  46.           }                 
  47.          
  48.          printf("bind success!\n");
  49.          
  50.          if(listen(sockfd, BACKLOG) == -1){
  51.                    perror("listen");
  52.                    exit(1);                  
  53.          }
  54.          
  55.          printf("listening - - - \n");
  56.          
  57.          if( (client_fd = accept(sockfd, (struct sockaddr *)&client_sockaddr, &sin_size)) == -1 ){
  58.                     perror("accept");
  59.                     exit(1);
  60.        }
  61.        
  62.         if(( recvbytes = recv(client_fd, bmpdata, MAXDATASIZE, 0)) == -1){
  63.                 perror("recv");
  64.                 exit(1);
  65.         }


  66.     for( i = 0  ; i< MAXDATASIZE ; i++ )
  67.          {   
  68.                    printf("%x - ",bmpdata[i] ) ;
  69.          }

  70. if ( nwrite = fwrite (bmpdata,MAXDATASIZE,1, fbmp  ) < 0)
  71.              {
  72.                      printf("Write  BMP error !\n");
  73.                     exit(-1);
  74.       }

  75.     fclose(fbmp);
  76.     close(sockfd);

  77. }


  78. ---------------client---------------------

  79. #include <sys/types.h>
  80. #include <sys/socket.h>
  81. #include <stdio.h>
  82. #include <stdlib.h>
  83. #include <errno.h>
  84. #include <string.h>
  85. #include <unistd.h>
  86. #include <netinet/in.h>
  87. #include <netdb.h>

  88. #define SERVPORT 3333

  89. #define MAXDATASIZE 100*100*3+54

  90. main( int argc , char *argv[] )
  91. {
  92.          struct hostent *host;
  93.    struct sockaddr_in serv_addr;
  94.          int sockfd,sendbytes;
  95.          char buf[MAXDATASIZE];
  96.          int bmpsize = 0,
  97.              i,
  98.              headersize = 0,
  99.              pixelsize = 0;
  100.          
  101.          FILE *fbmp;
  102.          char bmpdata[100*100*3+54];
  103.          
  104.         if (( fbmp = fopen("client.bmp", "r")) == NULL)
  105.                    {
  106.                    printf("Open client bmp error !\n");
  107.                    exit(-1);
  108.             }   
  109.   

  110.   fseek(fbmp,0,SEEK_SET);
  111.   fread(bmpdata,MAXDATASIZE,1,fbmp);
  112.   
  113.    if( argc < 2) {
  114.                    fprintf(stderr, "Please enter the server's hostname!\n");
  115.                    exit(1);
  116.    }
  117.    
  118.    if( (host = gethostbyname(argv[1])) == NULL ){
  119.               perror("gethostbyname");
  120.               exit(1);          
  121.    }
  122.          
  123.    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
  124.                    perror("socket");
  125.                    exit(1);
  126.    }

  127.    printf("socket success!,socket = %d\n",sockfd);
  128.    
  129.    serv_addr.sin_family = AF_INET;         
  130.    serv_addr.sin_port = htons(SERVPORT);                 
  131.    serv_addr.sin_addr = *( (struct in_addr *)host->h_addr );
  132.    
  133.    bzero(&(serv_addr.sin_zero), 8);
  134.    
  135.    if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1 ){
  136.        perror("connect");
  137.        exit(1);           
  138.     }                 
  139.          
  140.    printf("connect success!\n");
  141.          

  142.   if(( sendbytes = send(sockfd, bmpdata ,bmpsize, 0)) == -1){
  143.                 perror("send");
  144.                 exit(1);
  145.     }


  146.     for( i = 0  ; i< MAXDATASIZE ; i++ )
  147.          {   
  148.            printf("%x - ",bmpdata[i] ) ;
  149.          }
  150.          
  151.   printf("send over!\n");
  152.   
  153.   fclose(fbmp);
  154. close(sockfd);

  155. }

复制代码

论坛徽章:
0
27 [报告]
发表于 2008-02-20 09:27 |只看该作者
呵呵,应该是代码的问题,我做的传输文件程序windows和Linux通用
ttplayer.exe和mm.jpeg都能完好无损传输
注意文件要在程序自然退出时关闭喔:wink:

论坛徽章:
0
26 [报告]
发表于 2008-02-11 20:36 |只看该作者
原帖由 lxy9805287 于 2008-1-5 22:32 发表
你有没有做包传输的标志 比如  #..............$ 还有长度, 如果服务端接弄个缓冲区先把接受到的存起来,再根据标志和长度判断是否接受完整,


这个方法一点也不通用,都知道文件里面可能包含# $呢,最好的办法是CRC效验.
你的做法比较土.

论坛徽章:
0
25 [报告]
发表于 2008-02-08 01:00 |只看该作者
听说高版本的操作系统有sendfile函数,可以直接发送文件的内容。
不知道有没有对称的writefile函数,呵呵~

论坛徽章:
0
24 [报告]
发表于 2008-01-25 11:13 |只看该作者

回复 #1 rambo0808 的帖子

我觉得有可能是你的buf开的太大了,因为应用程序的局部变量都是在堆栈上的,一般堆栈的大小为1M~2m,你一个两个buf一共用了60k觉得有点大,不过也不一定啊,你可以试试把buf定义为全局变量试试。
还有就是应该以二进纸打开好一点吧

论坛徽章:
0
23 [报告]
发表于 2008-01-25 09:31 |只看该作者
应该是fopen()和fwrite()函数要用二进制打开或者写文件吧.

论坛徽章:
0
22 [报告]
发表于 2008-01-07 09:01 |只看该作者
建议做超时处理
retval = select(sockfd+1,&set, NULL,NULL,&timeo);
          if (retval<=0)
                      {
                perror("select");
                fprintf(fp,"timeout at %d!\n",i);
                break;
                      }
不知道能不能用上,呵呵

论坛徽章:
0
21 [报告]
发表于 2008-01-05 22:32 |只看该作者
你有没有做包传输的标志 比如  #..............$ 还有长度, 如果服务端接弄个缓冲区先把接受到的存起来,再根据标志和长度判断是否接受完整,

论坛徽章:
0
20 [报告]
发表于 2007-12-12 18:02 |只看该作者

回复 #10 rambo0808 的帖子

作为一个实验程序,折腾折腾,了解平台SOCKET的实现。这是个不错的例子。作为一个SOCKET编程应用,我觉得LZ的程序可能不是特别合适:
1、TCP/IP都有窗口大小的。即缓存大小。每个平台的缓存大小是不一样的。LZ的recv返回都是641078 bytes正是说明了这个问题。所以,一般不会把整个文件一次传给send。也不会一次性recv太多。一般是以MTU为界。
2、大家都知道网络通信里有个MTU,即一个IP数据包的大小是受通信线路的限制的。以太网是1500字节,减去IP头和TCP头只剩下1472字节。(好象是IPH=8,TCPH=20,有点忘。)所以,对于数据传输。一般的实现是,先读1K,然后发送1K,这样循环发送。太小了,会影响通信效率。如一次发送1字节,有可能会打包成一个只包含1字节有效数据的TCP包发送。当然,这个也不是必然,和平台实现有关。太大了,会受窗口大小限制。

论坛徽章:
0
19 [报告]
发表于 2007-12-08 00:13 |只看该作者
send或sendto有可能发送一部分数据,因为底层缓冲区已经满了。需要继续发送。
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP