TCP 传输图片失真

yu2xiangyang 2011-06-07 03:44:52
正在做一个项目,目前卡住了,主要是传输图片,总是失真。不知道大家有没有遇到过类似问题。
客户端(linux系统)传输图片到服务器(windows操作系统)。在服务器上建立一个MFC程序,显示接收到的图片。如果单步调试客户端的程序,服务器可以接收到图片,并且图片是完整的,不失真的。但是直接运行客户端的程序,服务器接收到的图片却是失真的,每次执行各种失真情况。
同时,我在vc下写了一个WIN32控制台应用程序的服务器,接收到的图片是完整的,但是在MFC下图片就不行了,纠结ING......

客户端程序(linux)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include<arpa/inet.h>

#define PIC_LEN 800
#define PORTNUM 6000
#define FALSE 0
#define TRUE 1
typedef int BOOL;

enum
{
//client name
USER_CLIENT1 = 1,
USER_CLIENT2,
USER_CLIENT3,
USER_CLIENT4,
USER_CLIENT5,
USER_CLIENT6,

//client message type
USER_DATA,
USER_PICTURE,
USER_REGISTER,
};

struct SendMsg
{
int cliNum;
int transType;
int tempVa;
int humVal;
int somkVal;
char picData[PIC_LEN];
int picDataLen;
BOOL picEnd;
};


void error(const char *msg)
{
perror(msg);
exit(0);
}


int main(int argc, char *argv[])
{
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");

int len;
const char *cp = "10.21.11.146";

struct sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORTNUM);
if ( 0 == inet_aton(cp, &serv_addr.sin_addr))
error("ERROR not valid address!");


FILE *fq = NULL;
SendMsg CliMsg;
CliMsg.cliNum = USER_CLIENT5;
CliMsg.transType = USER_REGISTER;
CliMsg.picEnd = FALSE;

if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");

if ( NULL == (fq = fopen("/home/yuxiangyang/xiaoyaxuan.jpg", "rb")) )
error("ERROR:file open error!");

write(sockfd,(char*)&CliMsg,sizeof(SendMsg));

bzero(CliMsg.picData,PIC_LEN);

CliMsg.transType = USER_PICTURE;

while(!feof(fq))
{
len = fread(CliMsg.picData, 1, PIC_LEN, fq);
CliMsg.picDataLen = len;
write(sockfd, (char*)&CliMsg, sizeof(SendMsg));
printf("send data ing ing ......\n");
usleep(6000);
}

CliMsg.picEnd = TRUE;

write(sockfd,(char*)&CliMsg,sizeof(SendMsg));
printf("transmit data over!\n");

while(1)
{
sleep(4000);
}

close(sockfd);
fclose(fq);
return 0;
}

服务器(win32控制台应用程序,图片接收是图片的)

#include "stdafx.h"
#include <iostream>
#include <WinSock2.h>

enum
{
USER_CLIENT1 = 1,
USER_CLIENT2,
USER_CLIENT3,
USER_CLIENT4,
USER_CLIENT5,
USER_CLIENT6,

USER_DATA,
USER_PICTURE,
USER_REGISTER,
};
struct recvMsg
{
int cliNum;
int transType;
int tempVa;
int humVal;
int somkVal;
char picData[800];
int picDataLen;
BOOL picEnd;
};
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 2, 2 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
return 1;
}


if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
return 1;
}

SOCKET listfd = socket(AF_INET, SOCK_STREAM, 0);
if( INVALID_SOCKET == listfd )
{
std::cout<<"sock initial error!"<<std::endl;
}
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);

if( SOCKET_ERROR == bind(listfd,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)))
{
std::cout<<"bind error!"<<std::endl;
}

if( SOCKET_ERROR == listen(listfd, 8))
{
std::cout<<"listen error!"<<std::endl;
}


SOCKET sockConn;
SOCKADDR_IN addrCli;
int len = sizeof(SOCKADDR);

sockConn = accept(listfd, (SOCKADDR*)&addrCli, &len);

if( sockConn == INVALID_SOCKET)
{
std::cout<<"accept client connect error!"<<std::endl;
}

std::cout<<"one client is connecting"<<std::endl;
printf("client address is %s\n", inet_ntoa(addrCli.sin_addr));

FILE *pic = fopen("F: \\fire.jpg","wb");
if( pic == NULL)
{
std::cout<<"open file error!"<<std::endl;
}


recvMsg mess;
while(1)
{
recv(sockConn, (char*)&mess, sizeof(recvMsg),0);

if(mess.transType == USER_PICTURE)
{
if( mess.picEnd != TRUE )
{
fwrite(mess.picData, 1, mess.picDataLen, pic);
std::cout<<"recving data"<<std::endl;
}
else
{
break;
}
}
}

closesocket(listfd);
fclose(pic);
return 0;
}

服务器(MFC图片接受程序)


if(USER_PICTURE == returnMsg.transType)
{
if(FALSE == returnMsg.picEnd)
{
switch(returnMsg.cliNum)
{
case USER_CLIENT1:
fwrite(returnMsg.picData, 1, returnMsg.picDataLen,picFile1);
break;



可能解释不是很清楚,希望大家积极留言
...全文
338 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
yu2xiangyang 2011-06-08
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 abxialiang 的回复:]
我想说下思路吧,上班没有时间看你的代码,你先用一个小文本文件(很小)来传送,对比接收到的文件与原文件是否一样.分析那些不一样的数据是怎么发生的.这个调试方法很有用.
[/Quote]
数据能接受完整了,根据9楼的思想做了验证,是数据包丢失的问题
yu2xiangyang 2011-06-08
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 shenyi0106 的回复:]
你看一下,是不是window和linux下的int大小不一致导致的?
还有字节对齐问题
[/Quote]
不是这方面的问题,我单步执行是正确的,根据1楼的指导,还是数据丢失的问题
yu2xiangyang 2011-06-08
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 kyotrue 的回复:]
数据没有接收全吧,你记录一下你收到的字节数和发送的是否一样。

单步执行,给了I/O很多时间,所以执行下去可能已经收到完整数据了。

本机使用TCP通讯,不能模拟网络上的情况的。
[/Quote]
我在客户机定义了一个计数器,在服务器定义了一个接受字节的计数器,果然是数据丢失掉了
zyyoung 2011-06-08
  • 打赏
  • 举报
回复
单步是可以的,那说明是图片 没有接收完整。可以做2进制对比。

粘包 比较可能存在,可以做上消息头。

另外接收、发送2方 加上校验,保证万无一失。
小驴 2011-06-07
  • 打赏
  • 举报
回复
学习ing
jamseyang 2011-06-07
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 abxialiang 的回复:]
我想说下思路吧,上班没有时间看你的代码,你先用一个小文本文件(很小)来传送,对比接收到的文件与原文件是否一样.分析那些不一样的数据是怎么发生的.这个调试方法很有用.
[/Quote]
UP, 我也用过,哈哈
smwhotjay 2011-06-07
  • 打赏
  • 举报
回复
没说的,你对两个图片crc校验下.以及比较下字节大小..反正是传输的问题
abxialiang 2011-06-07
  • 打赏
  • 举报
回复
我想说下思路吧,上班没有时间看你的代码,你先用一个小文本文件(很小)来传送,对比接收到的文件与原文件是否一样.分析那些不一样的数据是怎么发生的.这个调试方法很有用.
shenyi0106 2011-06-07
  • 打赏
  • 举报
回复
你看一下,是不是window和linux下的int大小不一致导致的?
还有字节对齐问题
kyotrue 2011-06-07
  • 打赏
  • 举报
回复
数据没有接收全吧,你记录一下你收到的字节数和发送的是否一样。

单步执行,给了I/O很多时间,所以执行下去可能已经收到完整数据了。

本机使用TCP通讯,不能模拟网络上的情况的。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧