dingzhou2008 发表于 2013-09-03 21:50

请问大家一个linux网络传输的问题?

本帖最后由 dingzhou2008 于 2013-09-08 12:52 编辑


下面是两个linux下网络传输程序,server.c和client.c,分别发送和接收照片数据。照片大小32K。编译后在ubuntu下运行正常图片正确,但交叉编译后server在开发板上运行,client在ubuntu下运行,接收到的图片数据能显示,但有错位。请大家帮忙分析一下。
server.c如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#include "proto.h"

#define BUFSIZE 128 //1024
#define STRSIZE 40

static void server_job(int sd) {

    char buf;
    int len, i, count;
    char jpgbuf;
    char statebuf;
    FILE *input_file;
    if ((input_file = fopen("1.jpg", "rb")) == NULL) {
      fprintf(stderr, "can't open 1.jpg\n");
      return;
    }
    fread(jpgbuf, 32768, 1, input_file);
    for (count = 0; count < 32; count++) {
      if (send(sd, jpgbuf+count*1024, 1024, 0) < 0) {
            printf("Send File:\t JPEG picture Failed\n");
      }
    }
}

int main() {
    char ipstr;
    int sd, newsd;
    struct sockaddr_in laddr, raddr;
    socklen_t raddr_len;
    pid_t pid;
    sd = socket(AF_INET, SOCK_STREAM, 0/*IPPROTO_TCP,IPPROTO_SCTP*/);
    if (sd < 0) {
      perror("socket()");
      exit(1);
    }

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

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

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

    if (listen(sd, 200) < 0) {
      perror("listen()");
      exit(1);
    }

    raddr_len = sizeof(raddr); /*!!!!!!!!*/
    while (1) {
      newsd = accept(sd, (void *) &raddr, &raddr_len);
      if (newsd < 0) {
            perror("accept()");
            exit(1);
      }
      pid = fork();
      if (pid < 0) {
            fprintf(stderr, "fork()");
            exit(1);
      }
      if (pid == 0) {
            close(sd);
            inet_ntop(AF_INET, &raddr.sin_addr, ipstr, STRSIZE);
            printf("Client:%s:%d\n", ipstr, ntohs(raddr.sin_port));
            server_job(newsd);
            close(newsd);
            exit(1);
      }
      close(newsd);
      wait(NULL);
    }
    exit(0);
}
client.c如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

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

char recieveBuffer;
int leftRecieveChars;
int currentIndex = 0;
int sd;
char getOneChar() {
    currentIndex++;
    if (leftRecieveChars == 0) {
      bzero(recieveBuffer, BUFFER_SIZE);
      do {
            leftRecieveChars = recv(sd, recieveBuffer, BUFFER_SIZE, 0);
            if (leftRecieveChars < 0) {
                printf("Server Recieve Data Failed!\n");
                exit(1);
            }
      } while (leftRecieveChars == 0);
      currentIndex = 0;
    }
    leftRecieveChars--;
    return recieveBuffer;
}

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

    int i, jpegSize;
    long long stamp;
    struct sockaddr_in raddr;
    char numberBuf;

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

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

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

    raddr.sin_family = AF_INET;
    raddr.sin_port = htons(atoi(SERVERPORT));
    inet_pton(AF_INET, argv, &raddr.sin_addr);

    if (connect(sd, (void *) &raddr, sizeof(raddr)) < 0) {
      perror("connect()");
      exit(1);
    }
    int count = 0, cnt = 0;
    char name;
    //while (1) {
    printf("Begin recieve data.the num is %d!\n", cnt);
    cnt++;
    jpegSize = 32768;
    char fileBuf;
    bzero(fileBuf, jpegSize);
    //printf("Begin receive JPG date !\n");
    for (count = 0; count < 32; count++) {
      leftRecieveChars = recv(sd, fileBuf + count * 1024, 1024, 0);
    }
    sprintf(name, "%d.jpg", count);
    count++;
    if (count >= 7)
      count = 0;
    fp = fopen(name, "w");
    int writeLength = fwrite(fileBuf, sizeof(char), 32768, fp);
    //printf("writeLength to file : %d\n", writeLength);
    if (writeLength < 32768) {
      printf("File:\t%s Write Failed\n", "1.jpeg");
      fclose(fp);
      exit(1);
    }
    fclose(fp);
    return 0;
}

dingzhou2008 发表于 2013-09-04 08:27

顶一个!大家帮忙啊!

huangya90 发表于 2013-09-04 14:02

本帖最后由 huangya90 于 2013-09-04 14:05 编辑

程序能运行,一般情况下是不会出问题的。但还是一个错误的程序。
tcp是面向字节流的,对于什么是面向字节流,请参考任何一本网络教材(其实很多人对tcp是面向字节流根本没有理解)。for (count = 0; count < 32; count++) {
      leftRecieveChars = recv(sd, fileBuf + count * 1024, 1024, 0);
    }这段代码中的每调用一次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个字节,如下图所示:
http://p13.freep.cn/p.aspx?u=v20_p13_photo_1309041339248573_0.jpg(左边的是文件错误的图片.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.请以后粘贴代码的时候使用插入的方式,不要直接粘贴,代码中出现笑脸了。

dingzhou2008 发表于 2013-09-06 16:58

多谢指点,说的太对了,严谨的作风让我自愧不如,我以后会改过,多谢大牛。
页: [1]
查看完整版本: 请问大家一个linux网络传输的问题?