c语言使用socket发送图片文件大小正确,但是无法打开是怎么回事?

使用c语言socket通信写了一个客户端与服务器,然后客户端向服务器发送文件,服务器接收。使用自己定义的数据包协议,服务器使用单线程epoll。最后测试时,文本文件发送没有问题,但是发送图片文件,最后图片的大小没有问题,但是无法打开,提示错误:分析 JPEG 图像文件时出错(Improper call to JPEG library in state 201) 。
文件的操作使用linux下系统调用read,write,open 。请问问题可能出现在哪里?

服务器代码:

#include<iostream>
#include<cstring>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/signal.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/epoll.h>
#include<errno.h>

using namespace std;

#define NET_PACKET_DATA_SIZE 5000 
#define PORT 6666   //服务器端口
#define LISTEN_SIZE 1023   //连接请求队列的最大长度
#define EPOLL_SIZE  1023   //epoll监听客户端的最大数目

int ss=0;///////////

/// 网络数据包包头  
struct NetPacketHeader  
{  
    unsigned short      wDataSize;  ///< 数据包大小,包含封包头和封包数据大小  
    unsigned short      wOpcode;    ///< 操作码  
};  

/// 网络数据包  
struct NetPacket  
{  
    NetPacketHeader     Header;                         ///< 包头  
    unsigned char       Data[NET_PACKET_DATA_SIZE];     ///< 数据  
};  



/// 网络操作码  
enum eNetOpcode  
{  
    NET_TEST1  = 1,  
};  

struct File_message
{
    char filename[100];  //文件名
    long filesize;  //文件大小
};

struct File_data
{
    char filename[100];  //文件名
    char buffer[1024]; //文件内容
};

void my_err(const char *err_string,int line)  //自定义错误函数
{
    cerr<<"line:"<<line<<endl; //输出错误发生在第几行
    perror(err_string);       //输出错误信息提示
    exit(1);
}

bool dealwithpacket(int conn_fd,char *recv_data,uint16_t wOpcode,int datasize)  //处理接收到的数据
{
    cout<<++ss<<":"<<"datasize"<<datasize<<endl;///////////////////

    int fd;
    if(wOpcode==1)  //接收文件信息
    { 
        File_message *file_message=(File_message*)recv_data;
        strcat(file_message->filename,"(2)");


        if((fd=open(file_message->filename,O_RDWR|O_APPEND|O_CREAT,0777))<0)
        {
            cout<<"创建文件失败"<<endl;
            return false;
        }
    }
    else if(wOpcode==2)  //接收文件内容
    {

        File_data * file_data=(File_data*)recv_data;

        strcat(file_data->filename,"(2)");
        if((fd=open(file_data->filename,O_RDWR|O_APPEND))<0)
        {
            cout<<"打开文件失败"<<endl;
            return false;
        }
        if(write(fd,file_data->buffer,datasize-sizeof(file_data->filename))<0)
        {
            cout<<"写入文件失败"<<endl;
            return false;
        }
        close(fd);
    }
   return true;

}

bool server_recv(int conn_fd)  //接收数据函数
{
    int nrecvsize=0; //一次接收到的数据大小
    int sum_recvsize=0; //总共收到的数据大小
    int packersize;   //数据包总大小
    int datasize;     //数据总大小
    char recv_buffer[10000];  //接收数据的buffer


    memset(recv_buffer,0,sizeof(recv_buffer));  //初始化接收buffer


    while(sum_recvsize!=sizeof(NetPacketHeader))
    {
        nrecvsize=recv(conn_fd,recv_buffer+sum_recvsize,sizeof(NetPacketHeader)-sum_recvsize,0);
        if(nrecvsize==0)
        {
            cout<<"从客户端接收数据失败"<<endl;
            return false;
        }
        sum_recvsize+=nrecvsize;

    }



    NetPacketHeader *phead=(NetPacketHeader*)recv_buffer;
    packersize=phead->wDataSize;  //数据包大小
    datasize=packersize-sizeof(NetPacketHeader);     //数据总大小




    while(sum_recvsize!=packersize)
    {
        nrecvsize=recv(conn_fd,recv_buffer+sum_recvsize,packersize-sum_recvsize,0);
        if(nrecvsize==0)
        {
            cout<<"从客户端接收数据失败"<<endl;
            return false;
        }
        sum_recvsize+=nrecvsize;
    }


    dealwithpacket(conn_fd,(char*)(phead+1),phead->wOpcode,datasize);



}
int main()
{

    int sock_fd;  //监听套接字
    int conn_fd;    //连接套接字
    int epollfd;  //epoll监听描述符
    socklen_t cli_len;  //记录连接套接字地址的大小
    struct epoll_event  event;   //epoll监听事件
    struct epoll_event*  events;  //epoll监听事件集合
    struct sockaddr_in cli_addr;  //客户端地址
    struct sockaddr_in serv_addr;   //服务器地址



    //创建一个套接字
    sock_fd=socket(AF_INET,SOCK_STREAM,0);
    if(sock_fd<0)
    {
        my_err("socket",__LINE__);
    }
    //设置该套接字使之可以重新绑定端口
    int optval=1;
    if(setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,(void*)&optval,sizeof(int))<0)
    {
        my_err("setsock",__LINE__);
    }
    //初始化服务器端地址结构
    memset(&serv_addr,0,sizeof(struct sockaddr_in));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_port=htons(PORT);
    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    if(bind(sock_fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in))<0)
    {
        my_err("bind",__LINE__);
    }
    //将套接字转化为监听套接字
    if(listen(sock_fd,LISTEN_SIZE)<0)
    {
        my_err("listen",__LINE__);
    }


    cli_len=sizeof(struct sockaddr_in);
    events=(struct epoll_event*)malloc(sizeof(struct epoll_event)*EPOLL_SIZE); //分配内存空间

    //创建一个监听描述符epoll,并将监听套接字加入监听列表
    epollfd=epoll_create(EPOLL_SIZE);
    if(epollfd==-1)
    {
        my_err("epollfd",__LINE__);
    }
    event.events = EPOLLIN;
    event.data.fd = sock_fd;
    if(epoll_ctl(epollfd,EPOLL_CTL_ADD,sock_fd,&event)<0)
    {
        my_err("epoll_ctl",__LINE__);
    }

    while(1)   //循环监听事件
    {
        int sum=0,i;
        sum=epoll_wait(epollfd,events,EPOLL_SIZE,-1);
        for(i=0;i<sum;i++)
        {
            if(events[i].data.fd==sock_fd)    //客户端请求连接
            {
                conn_fd=accept(sock_fd,(struct sockaddr*)&cli_addr,&cli_len);
                if(conn_fd<0)
                {
                    my_err("accept",__LINE__);
                }
                event.events = EPOLLIN | EPOLLRDHUP; //监听连接套接字的可读和退出
                event.data.fd = conn_fd;
                if(epoll_ctl(epollfd,EPOLL_CTL_ADD,conn_fd,&event)<0) //将新连接的套接字加入监听
                {
                    my_err("epoll",__LINE__);
                }
                cout<<"a connet is connected,ip is "<<inet_ntoa(cli_addr.sin_addr)<<endl;

            }
            else if(events[i].events&EPOLLIN)    //客户端发来数据
            {

                server_recv(events[i].data.fd);  //接收数据包并做处理

            }
            if(events[i].events&EPOLLRDHUP) //客户端退出
            {
                cout<<"a connet is quit,ip is "<<inet_ntoa(cli_addr.sin_addr)<<endl;
                epoll_ctl(epollfd,EPOLL_CTL_DEL,events[i].data.fd,&event);
                close(events[i].data.fd);
            }

        }
    }

}


客户端代码:

#include<iostream>
#include<string.h>
#include<math.h>
#include<sys/signal.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<errno.h>
#include<time.h>

#define PORT 6666   //服务器端口
#define NET_PACKET_DATA_SIZE 5000  
using namespace std;



struct File_message    //文件信息类
{
    char filename[100]; //文件名
    long filesize;  //文件大小

};

struct File_data   //文件内容类
{
    char filename[100];  //文件名
    char buffer[1024];  //文件内容
};

void my_err(const char *err_string,int line)  //自定义错误函数
{
    cerr<<"line:"<<line<<endl; //输出错误发生在第几行
    perror(err_string);       //输出错误信息提示
    exit(1);
}

/// 网络数据包包头  
struct NetPacketHeader  
{  
    unsigned short      wDataSize;  ///< 数据包大小,包含封包头和封包数据大小  
    unsigned short      wOpcode;    ///< 操作码  
};  

/// 网络数据包  
struct NetPacket  
{  
    NetPacketHeader     Header;                         ///< 包头  
    unsigned char       Data[NET_PACKET_DATA_SIZE];     ///< 数据  
};  


/// 网络操作码  
enum eNetOpcode  
{  
    NET_TEST1 = 1, //发送文件信息
    NET_TEST2 = 2, //发送文件内容
};  


bool send_to_serv(int conn_fd,char *data_buffer,int datasize,uint16_t wOpcode) //向服务器发送数据
{
    NetPacket send_packet;
    send_packet.Header.wDataSize=datasize+sizeof(NetPacketHeader);  //数据包大小
    send_packet.Header.wOpcode=wOpcode;
    memcpy(send_packet.Data,data_buffer,datasize);




    if(send(conn_fd,&send_packet,send_packet.Header.wDataSize,0))
       return true;
    else
       return false;

}


bool send_file(int conn_fd)   //向服务器发送文件
{
    char send_buffer[1024]; //发送数据buffer
    string filename;  //文件路径名
    int fd; //文件描述符
    struct stat file_buffer;  //文件属性buffer
    File_message file_message;   //文件信息
    File_data file_data;
    int nsize=0;
    int sum_size=0;


    int ss=0;///////////////////////////

    memset(send_buffer,0,sizeof(send_buffer));

    cout<<"请输入要发送的文件路径及文件名"<<endl;
    getline(cin,filename);

    if(fd=open(filename.c_str(),O_RDONLY)<0)
    {
        my_err("open file error",__LINE__);
    }
    if(stat(filename.c_str(),&file_buffer)<0)
    {
        my_err("stat file error",__LINE__);
    }

    strcpy(file_message.filename,filename.c_str());
    file_message.filesize=file_buffer.st_size;



    if(send_to_serv(conn_fd,(char*)&file_message,sizeof(file_data),NET_TEST1)<0)
    {
        cout<<"向服务器发送文件信息失败"<<endl;
    }

    cout<<++ss<<":"<<"datasize "<<sizeof(file_data)<<endl; //////////////////

    close(fd);
    if((fd=open(filename.c_str(),O_RDONLY))<0)
       {
           my_err("打开文件失败",__LINE__);
       }

    while(nsize=read(fd,send_buffer,sizeof(send_buffer)))
    {


        memset(&file_data,0,sizeof(file_data));
        strcpy(file_data.filename,filename.c_str());
        strncpy(file_data.buffer,send_buffer,nsize);

        send_to_serv(conn_fd,(char*)&file_data,nsize+sizeof(file_data.filename),NET_TEST2);


        cout<<++ss<<":"<<"datasize "<<sizeof(file_data.filename)+nsize<<endl;///////////

        sum_size+=nsize;
    }



    if(sum_size==file_buffer.st_size)
    {
        cout<<"发送文件成功"<<endl;
        close(fd);
        return true;
    }
    else
    {
        cout<<"发送文件出错"<<endl;
        close(fd);
        return false;
    }

}

int main(int argc ,char **argv)
{
    int conn_fd; //创建连接套接字
    struct sockaddr_in serv_addr; //储存服务器地址

    if(argc!=3)    //检测输入参数个数是否正确
    {
        cout<<"Usage: [-a] [serv_address]"<<endl;
        exit(1);
    }


    //初始化服务器地址结构
    memset(&serv_addr,0,sizeof(struct sockaddr_in));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_port=htons(PORT);

    //从命令行服务器地址
    for(int i=0;i<argc;i++)
    {
        if(strcmp("-a",argv[i])==0)
        {

            if(inet_aton(argv[i+1],&serv_addr.sin_addr)==0)
            {
                cout<<"invaild server ip address"<<endl;
                exit(1);
            }
            break;
        }
    }

    //检查是否少输入了某项参数
    if(serv_addr.sin_addr.s_addr==0)
    {
        cout<<"Usage: [-a] [serv_address]"<<endl;
        exit(1);
    }

    //创建一个TCP套接字
    conn_fd=socket(AF_INET,SOCK_STREAM,0);


    if(conn_fd<0)
    {
        my_err("connect",__LINE__);
    }

    //向服务器发送连接请求
    if(connect(conn_fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr))<0)
    {
        my_err("connect",__LINE__);
    }


    send_file(conn_fd);  //向服务器发送文件


    sleep(60);

}

改用unsigned char 数组作为读写数据的类型;不要用char数组

对比双方的数据是否一致。。。还有文件的文件格式。。。