C语言 服务器转发文件给客户端,客户端开线程接收文件出错

WindwaterSide 2017-07-27 04:11:21
传文件思路:客户端1 通过6000端口分包发送,服务器收到以链表的形式组装起来后保存,保存完毕通过5000端口转发给客户端2(这里由于我没有和其他电脑测试,所以我转回给自己),客户端2 运行时便开好线程接收。
现在遇到的问题是:客户端发送十几M文件给服务器没有问题,服务器转发出去也没有问题,客户端接收的包比发出的包多很多,而且重复,不知道什么原因,想请各位大神帮忙看看哪里除了问题。由于本人级别很低,连线程和socket之类的都不怎么懂,所以请尽量用浅显的语言告知。第一次发贴求问,有哪里做的不对请多多包涵。代码有点长,下面是我认为出问题的一部分,完整在链接里 http://pan.baidu.com/s/1pLSFqbh

DWORD WINAPI RecvFile(LPVOID IpParam)
{
int nStatus;
unsigned long cmd;
SOCKET socket_recvFile;
socket_recvFile = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
nStatus = ioctlsocket(socket_recvFile,FIONBIO,&cmd); //非阻塞模式

SOCKADDR_IN addrrcl;
addrrcl.sin_family = AF_INET;
addrrcl.sin_port = htons(5000);
addrrcl.sin_addr.s_addr = inet_addr("127.0.0.1");

bind(socket_recvFile,(SOCKADDR*)&addrrcl,sizeof(SOCKADDR));

int len = sizeof(sockaddr);

timeval tv;
while(1)
{
fd_set fdread;
FD_ZERO(&fdread);
FD_SET(socket_recvFile,&fdread);

tv.tv_sec = 0;
tv.tv_usec=1000;
select(0,&fdread,NULL,NULL,&tv);

if(FD_ISSET(socket_recvFile,&fdread))
{
SendFile_Req sendFile_Req;
SendFile_Req *q = &sendFile_Req;
recvfrom(socket_recvFile, (char *)q, sizeof(SendFile_Req),0,(SOCKADDR*)&addrrcl,&len);
printf("即将收到文件\n");
printf("将要收到包数:%d\n",q->PackageNum); //包数在下面用作循环结束条件
Assemble *head;
head = Create_LinkList(q->PackageNum);

int i;
int k = 0;

while(1)
{
FilePackage file_package;
FilePackage *p1 = &file_package;
recvfrom(socket_recvFile, (char *)p1, sizeof(FilePackage),0,(SOCKADDR*)&addrrcl,&len);
printf("接收到的包的序列号=%d\n",p1->seq);
/组装成带指针的结构体,下一步建成链表
Assemble assemble;
Assemble *p2 = &assemble;
p2 = (Assemble *)malloc(sizeof(Assemble));
memcpy(p2->recv.content,p1->content,60*1024);
strcpy(p2->recv._Filename, p1->_Filename);

Delete_LinkList(head, p1->seq);
Insert_LinkList(head, p2, p1->seq);
k++;
if ( k == q->PackageNum )
break;
}

//接收完毕,写入文件
Assemble Afile_package;
Assemble *p3 = &Afile_package;

char Location[1000] = "D:\\文件传输下载1\\";
p3 = head->next;
strcat(Location, p3->recv._Filename);
FILE *fp = fopen (Location, "wb");
rewind(fp);
int j;
for(i=1; i<=q->PackageNum; i++)
{
if ( i == sendFile_Req.PackageNum)
j = sendFile_Req.PackageSize%(60*1024);
else
j = 60*1024;
fwrite(p3->recv.content,sizeof(char),j,fp);
p3 = p3->next;
}
fclose(fp);

printf("\n\n**********接收文件成功**********\n\n");
}
else
Sleep(1000);
}
closesocket(socket_recvFile);
WSACleanup();
printf("exit\n");

}
...全文
353 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
独孤的根号3 2017-08-14
  • 打赏
  • 举报
回复
你用的不是TCP协议的,用的的UDP协议,这种协议传输,不保证数据的可靠性,以及是否到达,用TCP协议吧
WindwaterSide 2017-08-04
  • 打赏
  • 举报
回复
引用 7 楼 hzy_76 的回复:
关TCP什么事?楼主显然是用UDP的方式! UDP是无保证的协议,需要自己处理丢包、重复的问题,我估计你可能出现重复收包了。一般的处理方式是每个包用一个ID号标识,一来可以处理重复问题,二来用于确定顺序。另外加入收包确认机制,发送方在一定时间内如果收不到确认,要重发该ID的数据。
谢谢,交完作业已经好几天了,我也不是专业的,所以这个问题并不是很想要深究下去。但是怎么才能在发帖后得到及时的帮助,这点能教教我吗?
kakabulusi 2017-08-04
  • 打赏
  • 举报
回复
引用 10 楼 hzy_76 的回复:
这我也没有好办法,尤其是在论坛上,你的帖子被真正能帮你的人注意到,是无法量化时间的。如果你大概知道谁懂,就直接问他,这样最好了。要不就只能等,我在CSDN问一个问题,也是好多天后才有人提供比较好的思路,最终还是我自己搞定的。
自己搞定能有所提高,
老马何以识途 2017-08-04
  • 打赏
  • 举报
回复
这我也没有好办法,尤其是在论坛上,你的帖子被真正能帮你的人注意到,是无法量化时间的。如果你大概知道谁懂,就直接问他,这样最好了。要不就只能等,我在CSDN问一个问题,也是好多天后才有人提供比较好的思路,最终还是我自己搞定的。
老马何以识途 2017-08-03
  • 打赏
  • 举报
回复
关TCP什么事?楼主显然是用UDP的方式! UDP是无保证的协议,需要自己处理丢包、重复的问题,我估计你可能出现重复收包了。一般的处理方式是每个包用一个ID号标识,一来可以处理重复问题,二来用于确定顺序。另外加入收包确认机制,发送方在一定时间内如果收不到确认,要重发该ID的数据。
赵4老师 2017-08-03
  • 打赏
  • 举报
回复
引用 7 楼 hzy_76 的回复:
关TCP什么事?楼主显然是用UDP的方式! UDP是无保证的协议,需要自己处理丢包、重复的问题,我估计你可能出现重复收包了。一般的处理方式是每个包用一个ID号标识,一来可以处理重复问题,二来用于确定顺序。另外加入收包确认机制,发送方在一定时间内如果收不到确认,要重发该ID的数据。
不知道有多少前人掉在UDP Socket sendto(人多)sendto(病少)sendto(财富) recvfrom(人多)recvfrom(财富) 陷阱里面啊!
kakabulusi 2017-07-28
  • 打赏
  • 举报
回复
引用 2 楼 WindwaterSide 的回复:
[quote=引用 1 楼 kakabulusi 的回复:] 这就需要你了解一下TCP传输机制了。 TCP的三次握手、超时重传等机制。 三次握手保证了数据传输的可靠性,超时重传保证了数据的完整性。 但是,实际情况可能不尽如人意,超时重传可能会遇到实际发送成功,但是在指定时间内没有应答的情况,这种情况下会造成异常重传。【比如说,应答的响应时间如果超过500ms则重传该批次数据,由于网络情况,某段数据流传输时间开销可能超过了500ms才到达接收方,此时发送方不再响应该包正常收到的应答信息,而重新传递该批次数据。这一点也是TCP和UDP协议在本质上的区别】 TCP本身是流式套接字,解决完这个问题后,你还会遇到很多问题,比如说滑动窗口、粘包等,希望对你有帮助。
谢谢回复,但是明天就是ddl了,所以现在只是想知道我的程序出了什么问题,能帮我看看吗[/quote] 现在看可能来不及了,
yi19861209 2017-07-27
  • 打赏
  • 举报
回复
赵4老师 2017-07-27
  • 打赏
  • 举报
回复
不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊! http://bbs.csdn.net/topics/380167545
WindwaterSide 2017-07-27
  • 打赏
  • 举报
回复
引用 1 楼 kakabulusi 的回复:
这就需要你了解一下TCP传输机制了。 TCP的三次握手、超时重传等机制。 三次握手保证了数据传输的可靠性,超时重传保证了数据的完整性。 但是,实际情况可能不尽如人意,超时重传可能会遇到实际发送成功,但是在指定时间内没有应答的情况,这种情况下会造成异常重传。【比如说,应答的响应时间如果超过500ms则重传该批次数据,由于网络情况,某段数据流传输时间开销可能超过了500ms才到达接收方,此时发送方不再响应该包正常收到的应答信息,而重新传递该批次数据。这一点也是TCP和UDP协议在本质上的区别】 TCP本身是流式套接字,解决完这个问题后,你还会遇到很多问题,比如说滑动窗口、粘包等,希望对你有帮助。
谢谢回复,但是明天就是ddl了,所以现在只是想知道我的程序出了什么问题,能帮我看看吗
kakabulusi 2017-07-27
  • 打赏
  • 举报
回复
这就需要你了解一下TCP传输机制了。 TCP的三次握手、超时重传等机制。 三次握手保证了数据传输的可靠性,超时重传保证了数据的完整性。 但是,实际情况可能不尽如人意,超时重传可能会遇到实际发送成功,但是在指定时间内没有应答的情况,这种情况下会造成异常重传。【比如说,应答的响应时间如果超过500ms则重传该批次数据,由于网络情况,某段数据流传输时间开销可能超过了500ms才到达接收方,此时发送方不再响应该包正常收到的应答信息,而重新传递该批次数据。这一点也是TCP和UDP协议在本质上的区别】 TCP本身是流式套接字,解决完这个问题后,你还会遇到很多问题,比如说滑动窗口、粘包等,希望对你有帮助。

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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