18,356
社区成员
发帖
与我相关
我的任务
分享
int ret = recv(tcpsock, tmp, 1024*64, 0);
if ( ret < 0)
{
break;
}
///////////////////////////////////////////////////////////////
else if(strstr(tmp, "FILE") != NULL)
{
strcpy(buf, strtok(tmp, "FILE"));
sscanf(buf, "%llu%s", &file_size, file_name);
strcat(file_path,file_name);
/*AfxMessageBox(file_path);*/
length = strlen(buf) + 4;
if(re_file.Open(file_path,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite) == FALSE)
{
AfxMessageBox("打开文件失败!");
}
re_file.SeekToEnd();
re_file.Write((tmp + length), (ret - length));
recved_size += (ret - length);
re_file.Close();
if(recved_size == file_size)
{
CString str1;
str_commom_info.Format("文件名 :%s\r\n", file_name);
str1.Format( "文件大小 :%llu\r\n", file_size);
str_commom_info += str1;
str_commom_info += "接收成功!";
GetDlgItem(IDC_COMMOM_INFO)->SetWindowTextA(str_commom_info);
}
}
}
为什么有时候会是打开文件失败?
怎么做 能让它只打开一次,指定写完就关闭文件。
ULONGLONG endp = my_file.SeekToEnd();
文件指针移向 了文件尾, 应该加一句
my_file.SeektoBegin();
my_file.Open(file_path, CFile::modeRead)
file_size = my_file.GetLength();
ULONGLONG endp = my_file.SeekToEnd();
char * pszDate = (char *)malloc(MAX_BUF_SIZE);
while(my_file.GetPosition() <= endp)
{
memset(pszDate, 0, MAX_BUF_SIZE);
tFhdr * pFhdr = (tFhdr *)pszDate;
strcpy(pFhdr->filename, file_name.GetBuffer()); //文件名
pFhdr->totallen = file_size; //文件总长度
char * pDateBuf = (char *)pFhdr->date; //指向数据部分
if (file_size - total < MAX_BUF_SIZE - sizeof(tFhdr))
{
my_file.Read(pDateBuf, file_size - total);
cur_len = send(tcpsock, pDateBuf, (file_size - total), 0);
}
}
//这里Read后pDateBuf还是空,怎么回事啊!
[/quote]
注意!!!!
struct file_header结构必须是字节对齐的(编译器默认是8字节对齐),否则使用0长数组就会出现问题。
可以去google 一下0长数组,看看相关介绍。
还有,你确定你读文件传递的参数正确?file_size - total 是不是小于0了?[/quote]
不是。。好像是
char * pDateBuf = (char *)pFhdr->date; //指向数据部分
if (file_size - total < MAX_BUF_SIZE - sizeof(tFhdr))
{
my_file.Read(pDateBuf, file_size - total);
cur_len = send(tcpsock, pDateBuf, (file_size - total), 0);
AfxMessageBox(pDateBuf);
}
// char * pDateBuf = (char *)pFhdr->date; //指向数据部分
// 这样好像不能往pFhdr的date中存数据。
// 但前面分配了内存啊??
my_file.Open(file_path, CFile::modeRead)
file_size = my_file.GetLength();
ULONGLONG endp = my_file.SeekToEnd();
char * pszDate = (char *)malloc(MAX_BUF_SIZE);
while(my_file.GetPosition() <= endp)
{
memset(pszDate, 0, MAX_BUF_SIZE);
tFhdr * pFhdr = (tFhdr *)pszDate;
strcpy(pFhdr->filename, file_name.GetBuffer()); //文件名
pFhdr->totallen = file_size; //文件总长度
char * pDateBuf = (char *)pFhdr->date; //指向数据部分
if (file_size - total < MAX_BUF_SIZE - sizeof(tFhdr))
{
my_file.Read(pDateBuf, file_size - total);
cur_len = send(tcpsock, pDateBuf, (file_size - total), 0);
}
}
//这里Read后pDateBuf还是空,怎么回事啊!
[/quote]
注意!!!!
struct file_header结构必须是字节对齐的(编译器默认是8字节对齐),否则使用0长数组就会出现问题。
可以去google 一下0长数组,看看相关介绍。
还有,你确定你读文件传递的参数正确?file_size - total 是不是小于0了?
my_file.Open(file_path, CFile::modeRead)
file_size = my_file.GetLength();
ULONGLONG endp = my_file.SeekToEnd();
char * pszDate = (char *)malloc(MAX_BUF_SIZE);
while(my_file.GetPosition() <= endp)
{
memset(pszDate, 0, MAX_BUF_SIZE);
tFhdr * pFhdr = (tFhdr *)pszDate;
strcpy(pFhdr->filename, file_name.GetBuffer()); //文件名
pFhdr->totallen = file_size; //文件总长度
char * pDateBuf = (char *)pFhdr->date; //指向数据部分
if (file_size - total < MAX_BUF_SIZE - sizeof(tFhdr))
{
my_file.Read(pDateBuf, file_size - total);
cur_len = send(tcpsock, pDateBuf, (file_size - total), 0);
}
}
//这里Read后pDateBuf还是空,怎么回事啊!
#define MAX_BUFFER_SIZE 64 * 1024
//File Transmit Header
struct file_head
{
char filename[32]; //文件名(发送一个文件过程中,该字段固定不变)
UINT64 totallen; //文件总长度(发送一个文件过程中,该字段固定不变)
UINT64 datalen; //数据长度
UINT64 offset; //数据偏移
UINT64 checksum; //效验和(针对TCP,这个字段也可以不用)
char data[0]; //数据缓冲区(利用0长数组来表示数据缓冲区)
};
char *pszData = (char*)malloc(MAX_BUFFER_SIZE );
ZeroMemory(pszData, 0, MAX_BUFFER_SIZE );
struct file_head *pFileHeader = (struct file_head*)pszData;
strcpy(pFileHeader ->filename, "你的文件名.txt");
pFileHeader ->totallen = 文件总长度;
char *pDataBuf = pFileHeader + 1;
while (xxxx)
{
pFileHeader->datalen = 本次数据长度;
pFileHeader->offset = 本次数据在整个文件中的位置;
memcpy(pFileHeader->data, 文件数据, pFileHeader->datalen);
send(pszData , MAX_BUFFER_SIZE);
}
接收到数据以后,直接根据文件名找到文件句柄,然后Seek到offset处,直接write数据结束。
数据传输中间,不需要额外管理;这是我的大文件传输方式。仅供参考
memset(buf, 0, sizeof(buf));
len = recv(wParam, buf, 2048, 0);
if (len < 0) break;
if(buf[1]==0x4d && buf[2]==0x52 && buf[3]==0x44)
{
phead = (tMrHead *)buf;
if(phead->type == 2) //reflect 回应
{
pdata = (tGMrData *)phead->data;
inet_ntop(AF_INET, &pdata->refex_addr, refex_addr, sizeof(refex_addr));
str_mrdata.Format(_T("Reflex ip: %s\r\nReflex port: %d"),refex_addr, ntohs(pdata->refex_port));
GetDlgItem(IDC_MR_INFO)->SetWindowTextA(str_mrdata);
}
}
else
{
if(buf[0] == 'G' && buf[1] =='N') //文本标记 用于传信息
{
str_mydata.Format("%s", buf + 2);
GetDlgItem(IDC_MY_STRING)->SetWindowTextA(str_mydata);
}
else if((ptr = strstr(buf, "FILE")) != NULL) //文件标记
{
//.....
}
要处理这几种情况。 我开始在发送数据的时候是没错send 1024字节。
长度 + 文件名 + FILE(标记) + 文件数据 --------- 没次都这样的结构。直到数据发完。
后来看了一个别人写的是 先发数据长度 (一次) 再发文件名(一次) 最后是文件内容
在接收的时候用的
int flag = 1;
switch(lParam)
{
case 1:
break; //接收文件长度
case 2:
break; //接收文件名
case 3:
break; //接收文件内容
}
用这中方法实现我的所有需求,,有点问题,怎么可以兼容。。
这两种方法哪个好。。。
有没有更好的方法,,可以穿几G的文件,不卡的方法。。
CString info = "";
info.Format(_T("文件名:%s\r\n文件大小:%d\r\n接收成功!"), file_name, file_size);
GetDlgItem(IDC_COMMOM_INFO)->SetWindowTextA(info);
/*文件名:gnLog.h文件大小:2095接收成功!*/
为什么不换行,,我使用的多字节字符集。