rotation ㅤ    2017-06-04 13:57 采纳率: 50%
浏览 2429
已结题

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

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

  • 写回答

4条回答

  • rotation ㅤ    2017-06-04 13:53
    关注

    服务器代码:

    #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);
                }
    
            }
        }
    
    }
    
    
    
    评论

报告相同问题?

悬赏问题

  • ¥100 关于使用MATLAB中copularnd函数的问题
  • ¥20 在虚拟机的pycharm上
  • ¥15 jupyterthemes 设置完毕后没有效果
  • ¥15 matlab图像高斯低通滤波
  • ¥15 针对曲面部件的制孔路径规划,大家有什么思路吗
  • ¥15 钢筋实图交点识别,机器视觉代码
  • ¥15 如何在Linux系统中,但是在window系统上idea里面可以正常运行?(相关搜索:jar包)
  • ¥50 400g qsfp 光模块iphy方案
  • ¥15 两块ADC0804用proteus仿真时,出现异常
  • ¥15 关于风控系统,如何去选择