socket文件发送与接收的有关问题

socket文件发送与接收的问题
本人大学生菜鸟,写了一个局域网内文件发送和接收的程序,但出现了很奇怪的问题。
程序运行会出现“客户端已经连接上,服务器端没有连接上”;或者“两边都连接上了,但客户端提示发送失败,而服务器端提示接收成功,实际上文件并没有发送成功”。如下图所示:
socket文件发送与接收的有关问题
socket文件发送与接收的有关问题

服务器端:
#pragma comment (lib,"ws2_32.lib")
#include <winsock.h>
#include <stdio.h>

#define MAX_CLIENT_REQUEST 3 //最大客户连接请求数

int main()
{
WSADATA wsaData; //初始化

SOCKADDR_IN ServerAddr; //服务器地址
SOCKADDR_IN ClientAddr; //客户端地址
int ClientAddrLen=sizeof(ClientAddr); //客户端地址的长度
SOCKET ListenSocket; //监听套接字
SOCKET ConnectSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //连接套接字
ULONG SockMod=1; //用于设置非阻塞模式
FD_SET fdRead,fdWrite; //分别为读、写套接字集合
FILE *rfp,*wfp; //文件指针
int RW_SockNum; //可读写的套接字的数目
char buf[30]={0}; //缓冲区
int n=0; //接收文件时保存当次收到的字节数,发送文件时保存当次发送的字节数
int m=0; //读文件时当次读到的字节数
int h=0; //发送文件时保存一共已发送的字节数
int l=0; //保存文件长度
bool finish=false; //当次收发完成标志
union 
{
char a[4];
int b;
}data,flag; //FileLen:文件的大小。flag:标志,用于接收和发送反馈信息
data.b=0;
flag.b=1;

//初始化套接字空间
if ( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
{
printf("初始化失败!\n");
return -1;
}

//创建监听套接字
if ((ListenSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("创建监听套接字失败!\n");
return -1;
}

//给服务器地址赋值
ServerAddr.sin_family=AF_INET;
ServerAddr.sin_port=htons(8889); //端口号8889
ServerAddr.sin_addr.s_addr=inet_addr("127.0.0.1"); //如果用的是无线IP地址,连不同的路由就要改为不同的IP地址

//绑定地址
if (bind(ListenSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr)) == SOCKET_ERROR)
{
printf("绑定地址失败!\n");
return -1;
}

//进入监听状态
if (listen(ListenSocket,MAX_CLIENT_REQUEST) == SOCKET_ERROR)
{
printf("监听失败!\n");
return -1;
}

printf("等待客户请求......\n");

//允许ListenSocket的非阻塞模式
if (ioctlsocket(ListenSocket,FIONBIO,&SockMod) == SOCKET_ERROR)
{
printf("控制套接字模式失败!\n");
return -1;
}

while(1)
{
finish=false;

//初始化套接字集合,否则出现不可预期的后果
FD_ZERO(&fdRead); //清空套接字集合fdRead
FD_ZERO(&fdWrite); //清空套接字集合fdWrite
FD_SET(ListenSocket,&fdRead); //把ListenSocket加入fdRead

//更新可读写的套接字集合
if ((RW_SockNum=select(NULL,&fdRead,&fdWrite,NULL,NULL)) == SOCKET_ERROR)
{
printf("更新可读写套接字集合失败!\n");
return -1;
}

if (FD_ISSET(ListenSocket,&fdRead))
{
//接受客户端的连接请求
if ((ConnectSocket=accept(ListenSocket,(LPSOCKADDR)&ClientAddr,&ClientAddrLen)) == INVALID_SOCKET)
{
printf("建立连接失败!\n");
return -1;
}

//允许ConnectSocket的非阻塞模式
if (ioctlsocket(ConnectSocket,FIONBIO,&SockMod) == SOCKET_ERROR)
{
printf("控制套接字模式失败!\n");
return -1;
}
}

//打开或新建接收的文件
if ((wfp=fopen("F://server_receive.jpg","wb")) == NULL)
{
printf("文件打开失败!\n");
return -1;
}

//打开要发送的文件
if ((rfp=fopen("F://test.jpg","rb")) == NULL)
{
printf("打开文件失败!");
return -1;
}
fseek(rfp,0,SEEK_END);
l=data.b=ftell(rfp); //得到文件的大小

FD_SET(ConnectSocket,&fdRead);
FD_SET(ConnectSocket,&fdWrite);

//更新可读写的套接字集合
if ((RW_SockNum=select(NULL,&fdRead,&fdWrite,NULL,NULL)) == SOCKET_ERROR)
{
printf("更新可读写套接字集合失败!\n");
return -1;
}

while(!finish)
{
//接收部分
if (FD_ISSET(ConnectSocket,&fdRead))
{
memset(buf,0,sizeof(buf));

//接收文件的大小
if (flag.b==1)
{
if (recv(ConnectSocket,data.a,sizeof(data),0) == SOCKET_ERROR)
{
printf("接收文件大小失败!\n");
return -1;
}
flag.b=2;
}

//接收文件
if (flag.b==2)
{
memset(buf,0,sizeof(buf));
while((n=recv(ConnectSocket,buf,sizeof(buf),0))!=0)
{
if (n==SOCKET_ERROR)
{
//接收出错,通知客户端
data.b=0;
break;
}
fwrite(buf,n,1,wfp);
memset(buf,0,sizeof(buf));
if ((data.b-=n)<=0)
{
printf("接收文件完成!\n");
data.b=1;
break;
}
}
flag.b=5;
}

//接收反馈信息
if (flag.b==6)
{
if (recv(ConnectSocket,data.a,sizeof(data),0) == SOCKET_ERROR)
{
printf("接收信息失败!\n");
return -1;
}
if (data.b==0)
{
//收到出错信息,重发
flag.b=4;
}
else if (data.b==1)
{
//收到正确消息
finish=true;
break;
}
}
}

//发送部分
if (FD_ISSET(ConnectSocket,&fdWrite))
{
memset(buf,0,sizeof(buf));

//发送文件的大小
if (flag.b==3)
{
data.b=l;
if (send(ConnectSocket,data.a,sizeof(data),0)<0)