你一个客户端发700M的文件会不会有问题?没问题的话感觉是下面这句出问题:
getFileInformation();//打印文件信息你没加锁,两个读线程共写一个FILEHEAD file; //全局文件信息头

解决方案 »

  1.   

    int length_file_info=recv(newsock,(char *)&file,BUFFERSIZE,0);
    你试图接受1024的内容 而你file大小才多大 访问越界了 当然崩溃
      

  2.   

    看清楚 你这个file是FILEHEAD结构 这个结构多大呢?
      

  3.   


    不是这样子的,1024是接收的空间,真正传输的是length_file的值
    感觉有几个问题,你不停的用同一个buf去接收信息,当中那段是不会错的,到文件末尾,字符不到1024的时候这个buf就会出错了,你到网上学习下怎么样才能正确完整的接收不定大小文件的代码
    两个同时发700m的文件,是同一个文件吗,还是不同的文件?
      

  4.   

    我记得有个条件,当接收大小<1024的时候就跳出循环,而不是relength=0的时候
      

  5.   

    server的小黑框里就直接press any key to continue...了不接受了client还在发啊发
      

  6.   

    不同的文件啊。改了下,server还是自己退出不接受了//< >引用的是编译器的类库路径里面的头文件
    //" "引用的是你程序目录的相对路径中的头文件
    #include <stdio.h>
    #include <stdlib.h>
    #include <winsock2.h>
    #include <string.h>
    //添加默认链接库
    #pragma comment(lib,"ws2_32.lib")#define PORT 9999
    #define IPADDR "127.0.0.1"
    #define BACKLOG 20
    #define FILENAME 200
    #define LENGTH 200
    #define BUFFERSIZE 1024struct FILEHEAD  //文件信息结构
    {
    char path_buffer[LENGTH];//文件绝对路径加完整名
    char filename[LENGTH];//文件名
    char ext[LENGTH];//文件扩展名
    unsigned int length;//文件长度

    };//FILEHEAD file; //全局文件信息头
    struct sockaddr_in clientaddr;  //定义外部变量供线程函数调用//得到文件头信息,使用全局变量函数没有参数
    void getFileInformation(FILEHEAD file)
    {
    printf( "file information :\n" );
    //printf( "  Drive: %s\n", drive );
    //printf( "  Dir: %s\n", dir );
    printf( "  Filename: %s\n", file.filename );
    printf( "  Ext: %s\n", file.ext );
    printf( "  length is btye: %ld btye\n", file.length );
    }void showClientinfo()
    {
    //获取当前系统时间
    SYSTEMTIME st;
    GetLocalTime(&st);
    char SysDate[30]; //将systime中的时间转变为字符串存入SysDate[30];
    sprintf(SysDate, "%4d-%2d-%2d %2d:%2d:%2d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
    //Server显示客户端信息
    printf("%s Recv from Client [%s:%d] : %s\n", SysDate, inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
    //服务器向客户端回显信息
    }DWORD WINAPI RequestThread(LPVOID lparam)//线程函数,并发接收请求
    {
    FILEHEAD file;
    SOCKET newsock = (SOCKET)(LPVOID)lparam;
    char buf[BUFFERSIZE]={0};//接收缓冲区
    memset(buf,0,BUFFERSIZE);//缓冲区清零 showClientinfo();//显示连接信息 printf("等待接收文件头信息...\n");
    int length_file_info=recv(newsock,(char *)&file,sizeof(file),0);
    if (length_file_info == SOCKET_ERROR) 
    {
    printf("recv failed !\n");
    closesocket(newsock);
    //WSACleanup();
    return -1;
    } if (length_file_info<=0)
    {
    exit(0);//没有成功接收文件头信息
    } getFileInformation(file);//打印文件信息

    //拼接文件名为receive.文件后缀
    //char *s="receive";
    //memset(file.filename,0,LENGTH);
    //strcpy(file.filename,s);
    strcat(file.filename,file.ext);//给文件加上后缀名 FILE *fp=NULL;
    fp=fopen(file.filename,"wb+");
    if (NULL==fp)
    {
    perror("fail to build the file!!!\n");
    exit(0);
    } printf("要接收的文件名为:");
    printf(file.filename);//打印文件名
    printf ("\n catch file now....\n");

    int relength=0;//接收到字节的长度 Sleep(500);

    printf("开始接收...\n"); while (1)
    {
    relength=recv(newsock,buf,BUFFERSIZE,0);
    if (relength == SOCKET_ERROR) {
    printf("recv failed !\n");
    closesocket(newsock);
    //WSACleanup();
    return -1;
    } fwrite(buf,1,relength,fp);
    if (0==relength)
    {
    break;
    }
    printf(".");
    }
    printf("\n接收完成...\n"); fflush(fp);
    fclose(fp);
    fp=NULL; return 0;}
    int main(int argc,char *argv[])
    {
    //初始化winsock版本信息,加载动态链接库(dll)
    WSADATA wsData;
    if (WSAStartup(MAKEWORD(2,2),&wsData)!=0)
    {
    printf("WSAStartup failed !!!\n");
    return -1;
    } //创建监听套接字
    SOCKET socklisten;
    if((socklisten=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
    {
    printf("socket failed!!!\n");
    WSACleanup();
    return -1;
    } //设置服务器地址
    struct sockaddr_in servaddr; memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_port=htons(9999);
    servaddr.sin_addr.S_un.S_addr=inet_addr(IPADDR); //绑定socket地址结构到监听套接字
    if (bind(socklisten,(sockaddr *)&servaddr,sizeof(servaddr))!=0)
    {
    printf("binding failed!!!\n");
    closesocket(socklisten);
    WSACleanup();
    } //在server上运行监听
    if (listen(socklisten,20)!=0)
    {
    printf("listen failed !!!\n");
    closesocket(socklisten);
    WSACleanup();
    return -1;
    } //接收客户端的连接请求
    printf("TCP server is start!!!\n"); //clientaddrlength要有初值,
    int client_addr_length = sizeof(clientaddr);
    memset(&clientaddr,0,client_addr_length);
    SOCKET connect; //循环等待
    while (1)
    {
    if ((connect=accept(socklisten,(sockaddr *)&clientaddr,&client_addr_length))==INVALID_SOCKET)
    {
    printf("accept failed!!\n");
    closesocket(connect);
    WSACleanup();
    return -1;
    } //创建新线程
    DWORD ThreadID;
    CreateThread(NULL,0,RequestThread,(LPVOID)connect,0,&ThreadID);
    }}
      

  7.   

    把完整的文件名打出来看看,是不是两个线程操作的是同一个文件?
    printf(file.filename);//打印文件名    
      

  8.   

    我把server里面的线程里的printf去掉发现能多接受一点了
    server也没有崩溃,但是包没接受完#include<stdio.h>
    #include <stdlib.h>
    #include <winsock2.h>
    #include <string.h>#pragma comment(lib,"ws2_32.lib")#define PORT 9999
    #define IPADDR "127.0.0.1"
    #define BACKLOG 20
    #define FILENAME 200
    #define LENGTH 200
    #define BUFFERSIZE 1024*8struct FILEHEAD //FILE-head  struct
    {
    char filename[LENGTH];//file name
    unsigned int length;//the byte of the file};struct FILEDATA //FILE-data  struct
    {
    char filename[LENGTH];//file name
    char package[BUFFERSIZE];//package data
    unsigned int length;//the byte of the file
    unsigned int index;//index of the package};struct sockaddr_in clientaddr;  //Definition of the external variable for thread function callvoid getFileInformation(FILEHEAD file)
    {
    printf( "file information :\n" );
    printf( "  Filename: %s\n", file.filename );
    //printf( "  Ext: %s\n", file.ext );
    printf( " the file length is: %ld btye\n", file.length );
    }void showClientinfo()
    {
    //获取当前系统时间
    SYSTEMTIME st;
    GetLocalTime(&st);
    char SysDate[30];
    //将systime中的时间转变为字符串存入SysDate[30];
    sprintf(SysDate, "%4d-%2d-%2d %2d:%2d:%2d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
    //Server显示客户端信息
    printf("%s Recv from Client [%s:%d] : %s\n", SysDate, inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
    //服务器向客户端回显信息
    }DWORD WINAPI requestThread(LPVOID lparam)
    {
    FILEHEAD filehead;
    FILEDATA filedata;
    SOCKET newsock=(SOCKET)(LPVOID)lparam;
    //char buf[BUFFERSIZE]={0};
    memset(&filehead,0,sizeof(filehead));
    memset(&filedata,0,sizeof(filedata)); showClientinfo(); //printf("等待文件头信息 ...\n"); int length_file_info=recv(newsock,(char *)&filehead,sizeof(filehead),0);
    if (SOCKET_ERROR==length_file_info)
    {
    printf("receive failed!\n");
    closesocket(newsock);
    return -1;

    }
    if (length_file_info<=0)
    {
    exit(1);//异常退出
    } getFileInformation(filehead);//打印文件信息 FILE *fp=NULL;
    fp=fopen(filehead.filename,"wb+");
    if (NULL==fp)
    {
    perror("fail to build the file!!!\n");
    exit(1);
    }

    //printf("要接收的文件名为:");
    //printf(filehead.filename);//打印文件名
    //printf ("\n catch file now....\n");

    int recv_length=0;//接收到字节的长度

    //Sleep(100);

    printf("开始接收...\n");
    filedata.index=0;
    while (1)
    {
    recv_length=recv(newsock,(char *)&filedata,sizeof(filedata),0);
    if (recv_length == SOCKET_ERROR)
    {
    printf("recv failed !\n");
    closesocket(newsock);
    //WSACleanup();
    return -1;
    }

    fwrite(filedata.package,1,BUFFERSIZE,fp);
    if (0==recv_length)
    {
    break;
    }
    //printf("第%d块接收成功!\n",filedata.index);
    }
    printf("\n接收完成...\n\n");

    fflush(fp);
    fclose(fp);
    fp=NULL;

    return 0;
    }int main(int argc,char *argv[])
    {
    //初始化winsock版本信息,加载动态链接库(dll)
    WSADATA wsData;
    if (WSAStartup(MAKEWORD(2,2),&wsData)!=0)
    {
    printf("WSAStartup failed !!!\n");
    return -1;
    }

    //创建套接字
    SOCKET socklisten;
    if((socklisten=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
    {
    printf("socket failed!!!\n");
    WSACleanup();
    return -1;
    }

    //设置服务器地址
    struct sockaddr_in servaddr;

    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_port=htons(PORT);
    servaddr.sin_addr.S_un.S_addr=inet_addr(IPADDR);

    //绑定socket地址结构到监听套接字
    if (bind(socklisten,(sockaddr *)&servaddr,sizeof(servaddr))!=0)
    {
    printf("binding failed!!!\n");
    closesocket(socklisten);
    WSACleanup();
    }

    //在server上运行监听
    if (listen(socklisten,20)!=0)
    {
    printf("listen failed !!!\n");
    closesocket(socklisten);
    WSACleanup();
    return -1;
    }

    //接收客户端的连接请求
    printf("TCP server is start!!!\n");

    //clientaddrlength要有初值,
    int client_addr_length = sizeof(clientaddr);
    memset(&clientaddr,0,client_addr_length);
    SOCKET connect;

    //循环等待
    while (1)
    {
    if ((connect=accept(socklisten,(sockaddr *)&clientaddr,&client_addr_length))==INVALID_SOCKET)
    {
    printf("accept failed!!!\n");
    closesocket(connect);
    WSACleanup();
    return -1;
    }

    //创建新线程
    DWORD ThreadID;
    CreateThread(NULL,0,requestThread,(LPVOID)connect,0,&ThreadID);
    }

    }
      

  9.   

    在包头放一个整个包的长度 然后用循环一直到接收完这个包为止;发送端也需要这样int Recv(SOCKET s,  char* buf , len)
    {
        recv(s, buff, 4);//这个四个字节应该也要用循环接收的 你自己写吧。    int len = *(int*)buf
        int offset = 0;
        while(len >0)
        {
            int iRet = recv(s, buf + offset, len);
              if(iRet <= 0)
               {
                  return -1;
                }
             offset += iRet;
             len -= iRet;
         }
         return offset;
    }
      

  10.   

    int Recv(SOCKET s,  char* buf)
    {
        recv(s, buff, 4);//这个四个字节应该也要用循环接收的 你自己写吧。
     
        int len = *(int*)buf;
        int offset = 0;
        while(len >0)
        {
            int iRet = recv(s, buf + offset, len);
              if(iRet <= 0)
               {
                  return -1;
                }
             offset += iRet;
             len -= iRet;
         }
         return offset;
    }上面有错 改了一下
      

  11.   

    是乱包?不会吧,TCP 保证有序的。 你可能是包没收全, 如果是这样的话 按照我上面的方法做 就可以收全了。
      

  12.   

    你把recv_length的值和sizeof(filedata)的值打印出来,然后对比一下
      

  13.   

    我客户端这样传的应该没问题
    send(sock_trans,(char *)&filedata,sizeof(filedata),0);
      

  14.   

    #define FILENAME 200
    #define LENGTH 200
    #define BUFFERSIZE 1024*8
     
    struct FILEHEAD //FILE-head  struct
    {
        char filename[LENGTH];//file name
        unsigned int length;//the byte of the file
     
    };
     
    struct FILEDATA //FILE-data  struct
    {
        char filename[LENGTH];//file name
        char package[BUFFERSIZE];//package data
        unsigned int length;//the byte of the file
        unsigned int index;//index of the package};
    你一个包这么大 发送端明显也要改
      

  15.   

    http://www.cnblogs.com/staid/archive/2010/12/09/1895371.html
      

  16.   

    崩溃好像是因为,我的server里面printf的问题,但是现在发现包收过来是乱的,有的大文件就收不齐全,是不是得用点“高科技”什么的控制一下?
      

  17.   

    偶,我试了下,buffersize小一点还真好了。
      

  18.   

    不知道有多少前人掉在TCP Socket
    send(人多)send(病少)send(财富)
    recv(人多病)recv(少财富)
    陷阱里面啊!
    http://topic.csdn.net/u/20120210/09/51109ed0-07b9-41f2-b487-a51597f2ca01.html
      

  19.   

    http://blog.csdn.net/hanhuili/article/details/8491781
      

  20.   

    针对我的程序,结果就是,去掉线程函数中的printf(线程不安全的好像是、、、),然后改小缓冲区,问题大致就得到了解决。其他要真正保证数据一点都不要错的,需要重新设计包结构。
      

  21.   

    首先接收要判断数据报文长度,接收完一次,要更新已经接收长度和还没有接收的长度。还有没接收完一次,缓冲区大小的数据,要给buf的数据清零一下。