免费注册 查看新帖 |

Chinaunix

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

[Linux] 请问大家一个linux网络传输的问题? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-09-03 21:50 |只看该作者 |倒序浏览
本帖最后由 dingzhou2008 于 2013-09-08 12:52 编辑


下面是两个linux下网络传输程序,server.c和client.c,分别发送和接收照片数据。照片大小32K。编译后在ubuntu下运行正常图片正确,但交叉编译后server在开发板上运行,client在ubuntu下运行,接收到的图片数据能显示,但有错位。请大家帮忙分析一下。

  1. server.c如下:
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <sys/types.h>
  8. #include <string.h>
  9. #include "proto.h"

  10. #define BUFSIZE 128 //1024
  11. #define STRSIZE 40

  12. static void server_job(int sd) {

  13.     char buf[BUFSIZE];
  14.     int len, i, count;
  15.     char jpgbuf[1024 * 500];
  16.     char statebuf[40];
  17.     FILE *input_file;
  18.     if ((input_file = fopen("1.jpg", "rb")) == NULL) {
  19.         fprintf(stderr, "can't open 1.jpg\n");
  20.         return;
  21.     }
  22.     fread(jpgbuf, 32768, 1, input_file);
  23.     for (count = 0; count < 32; count++) {
  24.         if (send(sd, jpgbuf+count*1024, 1024, 0) < 0) {
  25.             printf("Send File:\t JPEG picture Failed\n");
  26.         }
  27.     }
  28. }

  29. int main() {
  30.     char ipstr[STRSIZE];
  31.     int sd, newsd;
  32.     struct sockaddr_in laddr, raddr;
  33.     socklen_t raddr_len;
  34.     pid_t pid;
  35.     sd = socket(AF_INET, SOCK_STREAM, 0/*IPPROTO_TCP,IPPROTO_SCTP*/);
  36.     if (sd < 0) {
  37.         perror("socket()");
  38.         exit(1);
  39.     }

  40.     int val = 1;
  41.     if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
  42.         perror("setsockopt(SO_REUSEADDR)");
  43.     }

  44.     laddr.sin_family = AF_INET;
  45.     laddr.sin_port = htons(atoi(SERVERPORT));
  46.     inet_pton(AF_INET, "0.0.0.0", &laddr.sin_addr);

  47.     if (bind(sd, (void *) &laddr, sizeof(laddr)) < 0) {
  48.         perror("bind()");
  49.         exit(1);
  50.     }

  51.     if (listen(sd, 200) < 0) {
  52.         perror("listen()");
  53.         exit(1);
  54.     }

  55.     raddr_len = sizeof(raddr); /*!!!!!!!!*/
  56.     while (1) {
  57.         newsd = accept(sd, (void *) &raddr, &raddr_len);
  58.         if (newsd < 0) {
  59.             perror("accept()");
  60.             exit(1);
  61.         }
  62.         pid = fork();
  63.         if (pid < 0) {
  64.             fprintf(stderr, "fork()");
  65.             exit(1);
  66.         }
  67.         if (pid == 0) {
  68.             close(sd);
  69.             inet_ntop(AF_INET, &raddr.sin_addr, ipstr, STRSIZE);
  70.             printf("Client:%s:%d\n", ipstr, ntohs(raddr.sin_port));
  71.             server_job(newsd);
  72.             close(newsd);
  73.             exit(1);
  74.         }
  75.         close(newsd);
  76.         wait(NULL);
  77.     }
  78.     exit(0);
  79. }
  80. client.c如下:
  81. #include <stdio.h>
  82. #include <stdlib.h>
  83. #include <string.h>
  84. #include <unistd.h>
  85. #include <sys/socket.h>
  86. #include <netinet/in.h>

  87. #include "proto.h"
  88. /* Address to accept any incoming messages.  */
  89. #define    INADDR_ANY        ((in_addr_t) 0x00000000)
  90. #define BUFFER_SIZE 1024
  91. /* Set N bytes of S to 0.  */
  92. extern void bzero(void *__s, size_t __n)
  93. __THROW __nonnull ((1));

  94. char recieveBuffer[BUFFER_SIZE];
  95. int leftRecieveChars;
  96. int currentIndex = 0;
  97. int sd;
  98. char getOneChar() {
  99.     currentIndex++;
  100.     if (leftRecieveChars == 0) {
  101.         bzero(recieveBuffer, BUFFER_SIZE);
  102.         do {
  103.             leftRecieveChars = recv(sd, recieveBuffer, BUFFER_SIZE, 0);
  104.             if (leftRecieveChars < 0) {
  105.                 printf("Server Recieve Data Failed!\n");
  106.                 exit(1);
  107.             }
  108.         } while (leftRecieveChars == 0);
  109.         currentIndex = 0;
  110.     }
  111.     leftRecieveChars--;
  112.     return recieveBuffer[currentIndex];
  113. }

  114. int main(int argc, char *argv[]) {
  115.     FILE *fp;

  116.     int i, jpegSize;
  117.     long long stamp;
  118.     struct sockaddr_in raddr;
  119.     char numberBuf[20];

  120.     if (argc < 2) {
  121.         fprintf(stderr, "Usage...\n");
  122.         exit(1);
  123.     }
  124.     //创建用于internet的流协议(TCP)socket,用client_socket代表客户机socket
  125.     sd = socket(AF_INET, SOCK_STREAM, 0);
  126.     if (sd < 0) {
  127.         perror("socket()");
  128.         exit(1);
  129.     }

  130.     //设置一个socket地址结构client_addr,代表客户机internet地址, 端口
  131.     struct sockaddr_in client_addr;
  132.     bzero(&client_addr, sizeof(client_addr)); //把一段内存区的内容全部设置为0
  133.     client_addr.sin_family = AF_INET; //internet协议族
  134.     client_addr.sin_addr.s_addr = htons(INADDR_ANY); //INADDR_ANY表示自动获取本机地址
  135.     client_addr.sin_port = htons(0); //0表示让系统自动分配一个空闲端口

  136.     //把客户机的socket和客户机的socket地址结构联系起来
  137.     if (bind(sd, (struct sockaddr*) &client_addr, sizeof(client_addr))) {
  138.         printf("Client Bind Port Failed!\n");
  139.         exit(1);
  140.     }

  141.     raddr.sin_family = AF_INET;
  142.     raddr.sin_port = htons(atoi(SERVERPORT));
  143.     inet_pton(AF_INET, argv[1], &raddr.sin_addr);

  144.     if (connect(sd, (void *) &raddr, sizeof(raddr)) < 0) {
  145.         perror("connect()");
  146.         exit(1);
  147.     }
  148.     int count = 0, cnt = 0;
  149.     char name[20];
  150.     //while (1) {
  151.     printf("Begin recieve data.the num is %d!\n", cnt);
  152.     cnt++;
  153.     jpegSize = 32768;
  154.     char fileBuf[jpegSize];
  155.     bzero(fileBuf, jpegSize);
  156.     //printf("Begin receive JPG date !\n");
  157.     for (count = 0; count < 32; count++) {
  158.         leftRecieveChars = recv(sd, fileBuf + count * 1024, 1024, 0);
  159.     }
  160.     sprintf(name, "%d.jpg", count);
  161.     count++;
  162.     if (count >= 7)
  163.         count = 0;
  164.     fp = fopen(name, "w");
  165.     int writeLength = fwrite(fileBuf, sizeof(char), 32768, fp);
  166.     //printf("writeLength to file : %d\n", writeLength);
  167.     if (writeLength < 32768) {
  168.         printf("File:\t%s Write Failed\n", "1.jpeg");
  169.         fclose(fp);
  170.         exit(1);
  171.     }
  172.     fclose(fp);
  173.     return 0;
  174. }

复制代码

论坛徽章:
0
2 [报告]
发表于 2013-09-04 08:27 |只看该作者
顶一个!大家帮忙啊!

论坛徽章:
4
申猴
日期:2013-08-23 12:42:13双鱼座
日期:2013-09-30 08:41:52摩羯座
日期:2013-10-29 07:47:43处女座
日期:2013-12-01 11:31:30
3 [报告]
发表于 2013-09-04 14:02 |只看该作者
本帖最后由 huangya90 于 2013-09-04 14:05 编辑

程序能运行,一般情况下是不会出问题的。但还是一个错误的程序。
tcp是面向字节流的,对于什么是面向字节流,请参考任何一本网络教材(其实很多人对tcp是面向字节流根本没有理解)。
  1. for (count = 0; count < 32; count++) {
  2.         leftRecieveChars = recv(sd, fileBuf + count * 1024, 1024, 0);
  3.     }
复制代码
这段代码中的每调用一次recv,不一定会收到1024个字节,所以调用32次可能收到小于1024*32个字节。这里就发生了这种情况。用命令

od -Ad -t u1 正确的图片.jpg >正确的图片.jpg.udecimal;  od -Ad -t u1 错误的图片.jpg >错误的图片.jpg.udecimal;  
可以得到两张图片的无符号整数类型。用命令
cmp 正确的图片.jpg 错误的图片.jpg
可以发现在第3921个字节出现了第一个不相同的字节。用vim打开文件:错误的图片.jpg.udecimal,正确的图片.jpg.udecimal。找到第3921个字节,如下图所示:
(左边的是文件错误的图片.jpg.udecimal,右边的是文件正确的图片.jpg.udecimal。图中的0003920表示第3921个字节)。错误的图片.jpg.udecimal从3921-4096个字节显示的数值是0(fileBuf是全局变量 ,每个字节默认值是0),而正确的图片.jpg.udecimal数值不是0。错误的图片.jpg.udecimal从地址0004960对应了正确的图片.jpg.udecima从地址0003920开始的数值,说明你在第四次调用recv的时候并没有收到 1024个字节。所以你接收了错误的数据。下面的recv调用也发生了这种情况。知道了原因, 我想你应该知道怎么改程序了。


另外说两点:
1.client.c中getOneChar() 有什么用?你都没有调用。
2.请以后粘贴代码的时候使用插入的方式,不要直接粘贴,代码中出现笑脸了。

论坛徽章:
0
4 [报告]
发表于 2013-09-06 16:58 |只看该作者
多谢指点,说的太对了,严谨的作风让我自愧不如,我以后会改过,多谢大牛。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP