windows 和 linux之间socket传输文件 写的一个程序,WINDOWS用作服务器,LINUX下面的是客户端,LINUX向WINDOWS传输文件,大小超过2M以上,经常数据不正常,WINDOWS用的SOCKET是异步模式的,经常是LINUX下面文件早早发完了,WINDOWS那边接个2M的文件最少要3-5分钟,还卡得要死,一次输送的是1K=1024 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 是否是模式问题,select 发送信号到界面时,有数据流了就直接写进文件了,猜想应该是要一个先写到缓存里面,等文件接收完了,再一次性写进文件吧 一次1K你这缓冲也有点太小了………………设个256KB我都觉得不过分,特别是局域网传输的时候,不要太小看网卡。另外传输文件瓶颈在于往磁盘里面写,你如果接收1KB数据就往磁盘里写1KB的话,自然会慢的多 不熟悉WINDOWS的编程,以前一直LINUX下面写程序 感觉这个服务器结构有点问题,select 通知发信号->处理信号->读数据->写缓存.因为一次发送只有1024,一个2M的文件最少发20次以上,这样回来 循环,很浪费效率.因为程序里面没有用到线程. LRESULT CTCP_IPChatDlg::OnSocket(WPARAM wParam,LPARAM lParam){ char test_str[201] = {0}; CString show_msg;// CString recv_file_name; char rcv_msg[1400] = {0} ; CString list_text; int list_num = 0;//list_Box列表的条目个数 int i = 0 char function_num[3]; static CFile *cur_file; static CString rcv_file_cache;//接收文件缓存区 switch (lParam) { case FD_ACCEPT: { show_msg = ""; int lenth=sizeof(client_addr); cur_client.client_socket = ::accept(server_socket,(struct sockaddr*)&client_addr,&lenth); cur_client.client_socket = cur_client.client_socket; for(i=0;i<30;i++) { if(connect_client[i].clientIP_addr == "") { connect_client[i].client_socket = cur_client.client_socket; connect_client[i].clientIP_addr = ::inet_ntoa(client_addr.sin_addr); cur_client.clientIP_addr = ::inet_ntoa(client_addr.sin_addr); break; } //memset(&connect_client[i],0x00,sizeof(struct client_msg_t)); } client_num = client_num + 1; //显示信息 show_msg.Format(L"有%d客户已经连接上了",client_num); GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg); show_msg += cur_client.clientIP_addr; show_msg+="\r\n"; show_msg+="登陆\r\n"; GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg); //GetDlgItem(IDC_MsgEdit)->SetWindowText(L"\r\n客户端1说:你好!"); break; } case FD_READ: { show_msg = ""; ::recv(wParam,rcv_msg,1024,0); if ( rcv_msg[0] != 0) { for(i=0;i<30;i++)//遍历,看是与那个客户端进行传输文件 { if((connect_client[i].client_socket == wParam)&&(connect_client[i].recv_file_lenth>0))//recv_file_lenth大于0,表示进行文件传输 { rcv_file_cache += rcv_msg; connect_client[i].recv_file_lenth = connect_client[i].recv_file_lenth - strlen(rcv_msg); if (connect_client[i].recv_file_lenth <= 0) { //文件接收完写入文件 if(cur_file!= NULL) cur_file->Write(&rcv_file_cache,rcv_file_cache.GetLength()); cur_file->Close(); //显示信息 GetDlgItem(IDC_MsgEdit)->GetWindowText(show_msg); show_msg +="文件接收完成\r\n"; GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg); } } else { memset(function_num,0x00,3); strncpy(function_num,rcv_msg+1,2); if (strcmp(function_num,"50") == 0)//功能号50,要接收文件 { char temp[20]; int file_name_lenth = 0; int file_lenth = 0; char file_name[30]; rcv_file_cache = "";//接收文件缓存 memset(temp,0x00,20); memset(file_name,0x00,30); strncpy(temp,rcv_msg+3,2); file_name_lenth = atoi(temp);//文件名的长度 strncpy(file_name,rcv_msg+5,file_name_lenth);//文件名 memset(temp,0x00,20); strncpy(temp,rcv_msg+5+file_name_lenth,strlen(rcv_msg)-5-file_name_lenth ); connect_client[i].recv_file_lenth = atoi(temp);//文件的长度 CString csFilter; //文件类型 CString file_name_str; file_name_str = file_name; { GetDlgItem(IDC_MsgEdit)->GetWindowText(show_msg); show_msg += "\r\n"; show_msg += file_name; GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg); } CFileDialog filedlg(false,NULL,file_name_str,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,NULL,NULL);//定义文件对话框 filedlg.m_ofn.lpstrFileTitle = (LPWSTR) file_name;//在对话框中显示文件名 if(filedlg.DoModal() == IDOK)//显示文件保存对话框 { CString str; str = filedlg.GetPathName();//保存的文件路径,包括了文件名 cur_file = new CFile(str,CFile::modeCreate | CFile::modeWrite);//根据文件名创建文件 if (cur_file == NULL)//如果文件不存在 { //return; } } ::send(connect_client[i].client_socket,"OK",3,0);//应答OK } else//普通聊天通讯 { //显示聊天的内容 GetDlgItem(IDC_MsgEdit)->GetWindowText(show_msg); show_msg += "\r\n"; show_msg +=connect_client[i].clientIP_addr; show_msg += "对您说:"; show_msg += rcv_msg; show_msg += ""; GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg); if (strcmp(rcv_msg,"recv_file") == 0)//如果是recv_file,应答OK { ::send(connect_client[i].client_socket,"OK",3,0); } } } break; } } break; } case FD_CLOSE: { show_msg = ""; list_text = ""; list_num = ((CListBox *)GetDlgItem(IDC_ClientList))->GetCount( ); ::closesocket(wParam);//关闭套接字 for(i=0;i<30;i++) { if(connect_client[i].client_socket == wParam) { //显示下线通知 GetDlgItem(IDC_MsgEdit)->GetWindowText(show_msg); show_msg += "\r\n"; show_msg += connect_client[i].clientIP_addr; show_msg += "客户端已经下线!\r\n"; GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg); //删除下线客户的在列表框的信息 for(i=0;i<list_num;i++) { ((CListBox *)GetDlgItem(IDC_ClientList))->GetText(i,list_text); if ( list_text == connect_client[i].clientIP_addr )//函数可以根据当前列表框的序号读取当前选择的项目 { ((CListBox *)GetDlgItem(IDC_ClientList))->DeleteString(i);//(::inet_ntoa(client_addr.sin_addr)); break; } } connect_client[i].client_socket = 0; connect_client[i].clientIP_addr = ""; connect_client[i].client_name = ""; break; } } break; } } return TRUE;} 关于CS_PARENTDC的问题 如何才能接收到按键消息? 如何快速显示文本? 欢迎VC爱好者加入--VC联盟(32956253) 求助:基于对话框的程序不能弹出主对话框是什么原因? 如何响应Delete和Insert等键 对话框在什么时候才会调用OnChar 函数 请问收发邮件的WIN32API是什么? JAVA 2 路径如何配置 高分求购VC中ADO连VFP的dbf文件进行操作的源代码 如何实现ftp拖动下载?? 基于对话框绘制的曲线,怎样保存出来?
设个256KB我都觉得不过分,特别是局域网传输的时候,不要太小看网卡。另外传输文件瓶颈在于往磁盘里面写,你如果接收1KB数据就往磁盘里写1KB的话,自然会慢的多
{ char test_str[201] = {0};
CString show_msg;//
CString recv_file_name;
char rcv_msg[1400] = {0} ;
CString list_text;
int list_num = 0;//list_Box列表的条目个数
int i = 0
char function_num[3];
static CFile *cur_file;
static CString rcv_file_cache;//接收文件缓存区 switch (lParam)
{
case FD_ACCEPT:
{
show_msg = "";
int lenth=sizeof(client_addr);
cur_client.client_socket = ::accept(server_socket,(struct sockaddr*)&client_addr,&lenth); cur_client.client_socket = cur_client.client_socket;
for(i=0;i<30;i++)
{
if(connect_client[i].clientIP_addr == "")
{
connect_client[i].client_socket = cur_client.client_socket;
connect_client[i].clientIP_addr = ::inet_ntoa(client_addr.sin_addr);
cur_client.clientIP_addr = ::inet_ntoa(client_addr.sin_addr);
break;
}
//memset(&connect_client[i],0x00,sizeof(struct client_msg_t));
}
client_num = client_num + 1;
//显示信息
show_msg.Format(L"有%d客户已经连接上了",client_num);
GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg);
show_msg += cur_client.clientIP_addr;
show_msg+="\r\n";
show_msg+="登陆\r\n";
GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg);
//GetDlgItem(IDC_MsgEdit)->SetWindowText(L"\r\n客户端1说:你好!");
break;
}
case FD_READ:
{
show_msg = ""; ::recv(wParam,rcv_msg,1024,0); if ( rcv_msg[0] != 0)
{
for(i=0;i<30;i++)//遍历,看是与那个客户端进行传输文件
{
if((connect_client[i].client_socket == wParam)&&(connect_client[i].recv_file_lenth>0))//recv_file_lenth大于0,表示进行文件传输
{
rcv_file_cache += rcv_msg;
connect_client[i].recv_file_lenth = connect_client[i].recv_file_lenth - strlen(rcv_msg);
if (connect_client[i].recv_file_lenth <= 0)
{
//文件接收完写入文件
if(cur_file!= NULL)
cur_file->Write(&rcv_file_cache,rcv_file_cache.GetLength());
cur_file->Close();
//显示信息
GetDlgItem(IDC_MsgEdit)->GetWindowText(show_msg);
show_msg +="文件接收完成\r\n";
GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg);
}
}
else
{
memset(function_num,0x00,3);
strncpy(function_num,rcv_msg+1,2);
if (strcmp(function_num,"50") == 0)//功能号50,要接收文件
{
char temp[20];
int file_name_lenth = 0;
int file_lenth = 0;
char file_name[30];
rcv_file_cache = "";//接收文件缓存
memset(temp,0x00,20);
memset(file_name,0x00,30);
strncpy(temp,rcv_msg+3,2);
file_name_lenth = atoi(temp);//文件名的长度
strncpy(file_name,rcv_msg+5,file_name_lenth);//文件名
memset(temp,0x00,20);
strncpy(temp,rcv_msg+5+file_name_lenth,strlen(rcv_msg)-5-file_name_lenth );
connect_client[i].recv_file_lenth = atoi(temp);//文件的长度 CString csFilter; //文件类型
CString file_name_str;
file_name_str = file_name;
{
GetDlgItem(IDC_MsgEdit)->GetWindowText(show_msg);
show_msg += "\r\n";
show_msg += file_name; GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg);
}
CFileDialog filedlg(false,NULL,file_name_str,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,NULL,NULL);//定义文件对话框 filedlg.m_ofn.lpstrFileTitle = (LPWSTR) file_name;//在对话框中显示文件名
if(filedlg.DoModal() == IDOK)//显示文件保存对话框
{
CString str;
str = filedlg.GetPathName();//保存的文件路径,包括了文件名
cur_file = new CFile(str,CFile::modeCreate | CFile::modeWrite);//根据文件名创建文件
if (cur_file == NULL)//如果文件不存在
{
//return;
}
}
::send(connect_client[i].client_socket,"OK",3,0);//应答OK
}
else//普通聊天通讯
{
//显示聊天的内容
GetDlgItem(IDC_MsgEdit)->GetWindowText(show_msg);
show_msg += "\r\n";
show_msg +=connect_client[i].clientIP_addr;
show_msg += "对您说:";
show_msg += rcv_msg;
show_msg += "";
GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg);
if (strcmp(rcv_msg,"recv_file") == 0)//如果是recv_file,应答OK
{
::send(connect_client[i].client_socket,"OK",3,0);
}
} }
break;
} }
break;
}
case FD_CLOSE:
{
show_msg = "";
list_text = "";
list_num = ((CListBox *)GetDlgItem(IDC_ClientList))->GetCount( ); ::closesocket(wParam);//关闭套接字
for(i=0;i<30;i++)
{
if(connect_client[i].client_socket == wParam)
{
//显示下线通知
GetDlgItem(IDC_MsgEdit)->GetWindowText(show_msg);
show_msg += "\r\n";
show_msg += connect_client[i].clientIP_addr;
show_msg += "客户端已经下线!\r\n";
GetDlgItem(IDC_MsgEdit)->SetWindowText(show_msg);
//删除下线客户的在列表框的信息
for(i=0;i<list_num;i++)
{
((CListBox *)GetDlgItem(IDC_ClientList))->GetText(i,list_text);
if ( list_text == connect_client[i].clientIP_addr )//函数可以根据当前列表框的序号读取当前选择的项目
{
((CListBox *)GetDlgItem(IDC_ClientList))->DeleteString(i);//(::inet_ntoa(client_addr.sin_addr));
break;
}
}
connect_client[i].client_socket = 0;
connect_client[i].clientIP_addr = "";
connect_client[i].client_name = "";
break;
}
}
break;
}
}
return TRUE;
}