‘壹’ 我用MFC的CSocket做了一个向服务器上传文件的程序,但是服务器端没有反应,哪位大神能帮我一下!
1、服务器端端口是否正确打开。
2、客户端和服务端是否握手成功。
3、服务器端软件部分协议是否正确。
4、没看到你的“主要代码”,你链接的是每个人自己的网络空间。
‘贰’ MFC怎么实现通过网络传送文件
很大的文件, 如果楼主没什么时间去研究校验 丢包重发 等等功能的话 就直接用CSOCKET 然后用TCP 直接连接就好咯
C/C++ code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
void SendFile()
{
#define PORT 34000 /// Select any free port you wish
AfxSocketInit(NULL);
CSocket sockSrvr;
sockSrvr.Create(PORT); // Creates our server socket
sockSrvr.Listen(); // Start listening for the client at PORT
CSocket sockRecv;
sockSrvr.Accept(sockRecv); // Use another CSocket to accept the connection
CFile myFile;
myFile.Open("C:\\ANYFILE.EXE", CFile::modeRead | CFile::typeBinary);
int myFileLength = myFile.GetLength(); // Going to send the correct File Size
sockRecv.Send(&myFileLength, 4); // 4 bytes long
byte* data = new byte[myFileLength];
myFile.Read(data, myFileLength);
sockRecv.Send(data, myFileLength); //Send the whole thing now
myFile.Close();
delete data;
sockRecv.Close();
}
以下是客户端代码 void GetFile()
{
#define PORT 34000 /// Select any free port you wish
AfxSocketInit(NULL);
CSocket sockClient;
sockClient.Create();
// "127.0.0.1" is the IP to your server, same port
sockClient.Connect("127.0.0.1", PORT);
int dataLength;
sockClient.Receive(&dataLength, 4); //Now we get the File Size first
byte* data = new byte[dataLength];
sockClient.Receive(data, dataLength); //Get the whole thing
CFile destFile("C:\\temp\\ANYFILE.EXE",
CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
destFile.Write(data, dataLength); // Write it
destFile.Close();
delete data;
sockClient.Close();
}
‘叁’ 基于mfc的socket编程怎么进行文件传输
1. 采用了多线程的方法,文件传输时使用AfxBeginThread()开启新线程
void CClientsockDlg::OnBnClickedSend()
{
pThreadSend = AfxBeginThread(Thread_Send,this);/
}
文件的发送和接收都开起了新线程
UINTThread_Send(LPVOID lpParam)
{
代码略…
}
2. 支持从配置文件configuration.ini中获取服务器参数
采用GetPrivateProfileString()和GetPrivateProfileInt()分别获取位于ServerConfiguration.ini文件中的String类型的IP和int类型的port
CString IP;
int port;
GetPrivateProfileString
(L"ServerConfiguration",L"IP",L"没有读取到数据!",IP.GetBuffer(10),10,L".\\configuration.ini");
port=GetPrivateProfileInt(L"ServerConfiguration",L"port",0,L".\\configuration.ini");
3. 采用了面向对象的设计方式,功能之间按模块划分
MFC本身具有良好的面向对象的特性,本程序严格按照MFC框架结构编写代码,每个按钮对应一个功能函数,降低了代码之间的耦合性,有利于程序的扩展和复用。
void CServersockDlg::OnBnClickedChoose()
void CServersockDlg::OnBnClickedSend()
void CServersockDlg::OnBnClickedRecvdata()
void CServersockDlg::OnBnClickedAbout()
void CServersockDlg::OnBnClickedWriteini()
4. 采用了CSocket类,代码相对更简单
CSocket类是MFC框架对socket编程中的winsockAPI的封装,因此通过这个类管理收发数据更加便利。代码也跟那个既简单易懂。
//创建
if(!Clientsock.Socket())
{
CString str;
str.Format(_T("Socket创建失败:%d"),GetLastError());
AfxMessageBox(str);
}
//连接
if(!Clientsock.Connect(IP,port))
{
CString str;
str.Format(_T("Socket连接失败:%d"),GetLastError());
AfxMessageBox(str);
}
else
{
AfxMessageBox(_T("Socket连接成功"));
代码略…
//发送
while(nSize<FindFileData.nFileSizeLow)
{
szBuff = new char[1024];
memset(szBuff,0x00,1024);
nSend =file.Read(szBuff,1024);
Clientsock.Send(szBuff,nSend);//发送数据
nSize += nSend;
}
file.Close();
delete szBuff;
Clientsock.Close();
(dlg->GetDlgItem(IDC_SEND))->EnableWindow(TRUE);
AfxMessageBox(_T("文件发送成功"));
dlg->SetDlgItemTextW(IDC_FILEPATHNAME,_T(""));
}
return 0;
5. 支持数据在服务器与客户端之间双向传输
本程序不但可以从客户端往服务器端传文件,而且可以从服务器端往客户端传文件。
但是互传文件的方式并不是完全相同的。
服务器端不管是接收文件还是发送文件始终是对绑定的端口进行监听。
//绑定
if(!Serversock.Bind(port))
{
CString str;
str.Format(_T("Socket绑定失败: %d"),GetLastError());
AfxMessageBox(str);
}
//监听
if(!Serversock.Listen(10))
{
CString str;
str.Format(_T("Socket监听失败:%d"),GetLastError());
AfxMessageBox(str);
}
客户端不管是接收文件还是发送文件始终是进行连接。
if(!Clientsock.Connect(IP,port))
{
CString str;
str.Format(_T("Socket连接失ì败:%d"),GetLastError());
AfxMessageBox(str);
}
else
{
略…
6. 完全图形化操作界面
二.软件使用说明
客户端主界面如图所示:
单击“选择文件”弹出文件对话框,选择一个要发送的文件,同时保存文件的路径。
单击“发送”则会读取ServerConfiguration.ini文件中的配置信息(IP和port),并根据此信息建立Socket连接,发送文件。注意:服务器端应该先单击了“接受客户端数据”,否则发送失败。
单击“接收”也会读取ServerConfiguration.ini文件中的配置信息(IP和port),并根据此信息建立Socket连接,接收文件。注意:服务器端应该先选择了向客户端发送的文件,并单击了“发送”,否则接受失败。
单击“读取配置文件”,会从ServerConfiguration.ini文件中读取配置信息,并以可编辑的文本形式显示出来,修改完后,单击“写入配置文件”,会将修改后的信息保存到配置文件中。
单击“关于”可以了解到软件相关信息。
代码注释里有更详细的说明
服务器端主界面如图所示
u 单击“接受客户端数据”,开始监听客户端的链接。
u 单击“选择文件”弹出文件对话框,选择一个要发送的文件,同时保存文件的路径。
u 单击“发送”则会读取ServerConfiguration.ini文件中的配置信息(port),并监听对应端口,准备发送文件。注意:客户端选择“接收”以后才能发送成功。
u 单击“读取配置文件”,会从ServerConfiguration.ini文件中读取配置信息,并以可编辑的文本形式显示出来,修改完后,单击“写入配置文件”,会将修改后的信息保存到配置文件中。但是服务器的IP是不可以修改的,它是在程序开始运行时从服务器所在机器的网卡上获取的。
u 单击“关于”可以了解到软件相关信息。
u 代码注释里有更详细的说明
代码下载地址:http://download.csdn.net/detail/leixiaohua1020/6320417
在此附上客户端使用CSocket发起连接的代码
[cpp] view plain
//----------------------------发送文件的线程------------------------------
UINT Thread_Send(LPVOID lpParam)
{
CClientsockDlg *dlg=(CClientsockDlg *)lpParam;
(dlg->GetDlgItem(IDC_SEND))->EnableWindow(FALSE);
CSocket Clientsock; //definition socket.
if(!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
}
CString IP;
int port;
GetPrivateProfileString(L"ServerConfiguration",L"IP",L"没有读取到数据!",IP.GetBuffer(100),100,L".\\configuration.ini");
port=GetPrivateProfileInt(L"ServerConfiguration",L"port",0,L".\\configuration.ini");
//创建
if(!Clientsock.Socket())
{
CString str;
str.Format(_T("Socket创建失败: %d"),GetLastError());
AfxMessageBox(str);
}
//连接
// if(!Clientsock.Connect(_T("127.0.0.1"),8088))
if(!Clientsock.Connect(IP,port))
{
CString str;
str.Format(_T("Socket连接失败: %d"),GetLastError());
AfxMessageBox(str);
}
else
{
AfxMessageBox(_T("Socket连接成功"));
WIN32_FIND_DATA FindFileData;
CString strPathName; //定义用来保存发送文件路径的CString对象
dlg->GetDlgItemTextW(IDC_FILEPATHNAME,strPathName);
FindClose(FindFirstFile(strPathName,&FindFileData));
Clientsock.Send(&FindFileData,sizeof(WIN32_FIND_DATA));
CFile file;
if(!file.Open(strPathName,CFile::modeRead|CFile::typeBinary))
{
AfxMessageBox(_T("文件不存在"));
return 1;
}
UINT nSize = 0;
UINT nSend = 0;
char *szBuff=NULL;
//发送
while(nSize<FindFileData.nFileSizeLow)
{
szBuff = new char[1024];
memset(szBuff,0x00,1024);
nSend = file.Read(szBuff,1024);
Clientsock.Send(szBuff,nSend);//发送数据
nSize += nSend;
}
file.Close();
delete szBuff;
Clientsock.Close();
(dlg->GetDlgItem(IDC_SEND))->EnableWindow(TRUE);
AfxMessageBox(_T("文件发送成功"));
dlg->SetDlgItemTextW(IDC_FILEPATHNAME,_T(""));
}
return 0;
}
以及服务器端使用CSocket监听的代码:
[cpp] view plain
//----------------------------监听文件的线程------------------------------
UINT Thread_Func(LPVOID lpParam) //接收文件的线程函数
{
CServersockDlg *dlg = (CServersockDlg *)lpParam; //获取对话框指针
(dlg->GetDlgItem(IDC_RECVDATA))->EnableWindow(FALSE);
if(!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
}
CString IP;
int port;
GetPrivateProfileString(L"ServerConfiguration",L"IP",L"没有读取到数据!",IP.GetBuffer(100),100,L".\\configuration.ini");
port=GetPrivateProfileInt(L"ServerConfiguration",L"port",0,L".\\configuration.ini");
char errBuf[100]={0};// 临时缓存
SYSTEMTIME t; //系统时间结构
CFile logErrorfile;
if(!logErrorfile.Open(_T("logErrorfile.txt"),CFile::modeCreate|CFile::modeReadWrite))
{
return 1;
}
CSocket Serversock;
CSocket Clientsock;
//创建
if(!Serversock.Socket())
{
CString str;
str.Format(_T("Socket创建失败: %d"),GetLastError());
AfxMessageBox(str);
}
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
Serversock.SetSockOpt(SO_REUSEADDR,(void *)&bOptVal,bOptLen,SOL_SOCKET);
//绑定
if(!Serversock.Bind(port))
{
CString str;
str.Format(_T("Socket绑定失败: %d"),GetLastError());
AfxMessageBox(str);
}
//监听
if(!Serversock.Listen(10))
{
CString str;
str.Format(_T("Socket监听失败: %d"),GetLastError());
AfxMessageBox(str);
}
GetLocalTime(&t);
sprintf_s(errBuf,"服务器已经启动...正在等待接收文件...\r\n时间:%d年%d月%d日 %2d:%2d:%2d \r\n",t.wYear,t.wMonth,t.wDay,
t.wHour,t.wMinute,t.wSecond);
int len = strlen(errBuf);
logErrorfile.Write(errBuf,len);
AfxMessageBox(_T("启动成功等待接收文件"));
while(1)
{
//AfxMessageBox(_T("服务器启动成功..."));
if(!Serversock.Accept(Clientsock)) //等待接收
{
continue;
}
else
{
WIN32_FIND_DATA FileInfo;
Clientsock.Receive(&FileInfo,sizeof(WIN32_FIND_DATA));
CFile file;
file.Open(FileInfo.cFileName,CFile::modeCreate|CFile::modeWrite);
//AfxMessageBox(FileInfo.cFileName);
int length = sizeof(FileInfo.cFileName);
logErrorfile.Write(FileInfo.cFileName,length);
//Receive文件的数据
UINT nSize = 0;
UINT nData = 0;
char *szBuff=NULL;
while(nSize<FileInfo.nFileSizeLow)
{
szBuff = new char[1024];
memset(szBuff,0x00,1024);
nData=Clientsock.Receive(szBuff,1024);
file.Write(szBuff,nData);
nSize+=nData;
}
delete szBuff;
Serversock.Close();
Clientsock.Close();
file.Close();
(dlg->GetDlgItem(IDC_RECVDATA))->EnableWindow(TRUE);
sprintf_s(errBuf,"文件接收成功...\r\n时间:%d年%d月%d日 %2d:%2d:%2d \r\n",t.wYear,t.wMonth,t.wDay,
t.wHour,t.wMinute,t.wSecond);
int len = strlen(errBuf);
logErrorfile.Write(errBuf,len);
//AfxMessageBox(_T("文件接收成功..."));
break;
}
}
return 0;
}
‘肆’ CSocket 怎么用
要看你怎么用了?可以用在TCP上,也可以用在UDP上。用在UDP上很简单的。你可以参阅msdn上的例子。UDP用法:先用CSocket定义个实例,然后再Create创建,指定端口和目的IP。然后可以用bind绑定端口。用的时候用sendto发送到指定端口和IP上,用Receive接收数据。网上也有很多的,可以去查查。
‘伍’ 通过socket发送图片,出现的一个问题
Receive不是接受全部数据之后才返回的。
for (;;)
{
char t[0x1000];
int n = sockClient.Receive(t, 0x1000);
if (n == 0)
{
break;
}
memcpy(data + dataLength, t, n);
dataLength += n;
}
写成类似这样的。
‘陆’ VC 如何发送接收文件
//通过TCP实现:
#define PORT 34000
void SendFile(LPCTSTR strFilename) //参数为发送文件路径及文件名
{
AfxSocketInit(NULL);
CSocket sockSrvr;
sockSrvr.Create(PORT); // Creates our server socket
sockSrvr.Listen(); // Start listening for the client at PORT
CSocket sockRecv;
sockSrvr.Accept(sockRecv); // Use another CSocket to accept the connection
CFile myFile;
if(!myFile.Open(strFilename, CFile::modeRead | CFile::typeBinary))
return;
int myFileLength = myFile.GetLength(); // Going to send the correct File Size
sockRecv.Send(&myFileLength, 4); // 4 bytes long
byte* data = new byte[myFileLength];
myFile.Read(data, myFileLength);
//1024
int iRet ;
iRet = sockRecv.Send(data, myFileLength); //Send the whole thing now
cout << "Ret = " << iRet << endl;
cout << "send file over!" << endl;
myFile.Close();
delete data;
sockRecv.Close();
}
//接收文件
#define PORT 34000
void GetFile(LPCTSTR strFilename) //参数为保存文件的路径及文件名
{
AfxSocketInit(NULL);
CSocket sockClient;
sockClient.Create();
sockClient.Connect("127.0.0.1", PORT); // "127.0.0.1" is the IP to your server, same port
int dataLength;
sockClient.Receive(&dataLength, 4); //Now we get the File Size first
byte* data = new byte[dataLength];
sockClient.Receive(data, dataLength); //Get the whole thing
CFile destFile(strFilename, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
destFile.Write(data, dataLength); // Write it
destFile.Close();
cout << "Recive file over!" << endl;
delete data;
sockClient.Close();
}
‘柒’ MFC CSocket.Send()怎么指定发送地址
如果是TCP,先连接到对方,send就不需要地址了。
如果是是UDP,有地址参数。用sendto。
‘捌’ 关于VC++ SOCKET文件传输问题
你先用readfile把文件一次性读到缓冲区中。这样下面的操作就和传送字符一样了。在将文件的长度通知客户端,让他分配好内存,准备接受文件。下面就将缓冲区的东西发送到客户端就行了。这个方法进行小文件传输还凑合,要传输大文件需要先把文件分块传送。
char *pBuffer = new char[1024];
DWORD dwReadSize = 0;
::ReadFile(hFile,pBuffer,1024,&dwReadSize,NULL);
send(socket,reinterpret_cast<char *>(pBuffer),dwReadSize,NULL);
当然,文件大小需要你用GetFileSize来获得
最后记得closehandle
‘玖’ VC SOCKET 文件传输程序问题
用VC6.0建立两个WIndows32 Console Application程序,并且选择一个支持MFC的程序,第一个程序中输入:
// server.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "server.h"
#include<afxsock.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
typedef struct _SOCKET_STREAM_FILE_INFO {
TCHAR szFileTitle[128]; //文件的标题名
DWORD dwFileAttributes; //文件的属性
FILETIME ftCreationTime; //文件的创建时间
FILETIME ftLastAccessTime; //文件的最后访问时间
FILETIME ftLastWriteTime; //文件的最后修改时间
DWORD nFileSizeHigh; //文件大小的高位双字
DWORD nFileSizeLow; //文件大小的低位双字
DWORD dwReserved0; //保留,为0
DWORD dwReserved1; //保留,为0
} SOCKET_STREAM_FILE_INFO, * PSOCKET_STREAM_FILE_INFO;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetMoleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
}
CSocket sockClient;
sockClient.Create();
if(!sockClient.Connect("127.0.0.1", 800))
{
AfxMessageBox("连接到对方机器失败!");
return 0;
}
SOCKET_STREAM_FILE_INFO StreamFileInfo;
sockClient.Receive(&StreamFileInfo,sizeof(SOCKET_STREAM_FILE_INFO));
CFile destFile(StreamFileInfo.szFileTitle, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
UINT dwRead = 0;
while(dwRead)
{
byte* data = new byte[1024];
memset(data,0,1024);
UINT dw=sockClient.Receive(data, 1024);
destFile.Write(data, dw);
dwRead+=dw;
}
SetFileTime((HANDLE)destFile.m_hFile,&StreamFileInfo.ftCreationTime,
&StreamFileInfo.ftLastAccessTime,&StreamFileInfo.ftLastWriteTime);
destFile.Close();
SetFileAttributes(StreamFileInfo.szFileTitle,StreamFileInfo.dwFileAttributes);
sockClient.Close();
AfxMessageBox("接收完毕!");
return nRetCode;
}
另外一个程序输入:
// client.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "client.h"
#include <afxsock.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
typedef struct _SOCKET_STREAM_FILE_INFO {
TCHAR szFileTitle[128]; //文件的标题名
DWORD dwFileAttributes; //文件的属性
FILETIME ftCreationTime; //文件的创建时间
FILETIME ftLastAccessTime; //文件的最后访问时间
FILETIME ftLastWriteTime; //文件的最后修改时间
DWORD nFileSizeHigh; //文件大小的高位双字
DWORD nFileSizeLow; //文件大小的低位双字
DWORD dwReserved0; //保留,为0
DWORD dwReserved1; //保留,为0
} SOCKET_STREAM_FILE_INFO, * PSOCKET_STREAM_FILE_INFO;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetMoleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
}
CFile myFile;
CString filename="123.txt";
if(!myFile.Open(filename, CFile::modeRead | CFile::typeBinary))
{
AfxMessageBox("文件不存在!",MB_OK|MB_ICONERROR);
return 0;
}
CSocket sockSrvr;
sockSrvr.Create(800);
sockSrvr.Listen();
CSocket sockRecv;
sockSrvr.Accept(sockRecv);
SOCKET_STREAM_FILE_INFO StreamFileInfo;
WIN32_FIND_DATA FindFileData;
FindClose(FindFirstFile(filename,&FindFileData));
memset(&StreamFileInfo,0,sizeof(SOCKET_STREAM_FILE_INFO));
strcpy(StreamFileInfo.szFileTitle,myFile.GetFileTitle());
StreamFileInfo.dwFileAttributes = FindFileData.dwFileAttributes;
StreamFileInfo.ftCreationTime = FindFileData.ftCreationTime;
StreamFileInfo.ftLastAccessTime = FindFileData.ftLastAccessTime;
StreamFileInfo.ftLastWriteTime = FindFileData.ftLastWriteTime;
StreamFileInfo.nFileSizeHigh = FindFileData.nFileSizeHigh;
StreamFileInfo.nFileSizeLow = FindFileData.nFileSizeLow;
sockRecv.Send(&StreamFileInfo,sizeof(SOCKET_STREAM_FILE_INFO));
UINT dwRead=0;
while(dwRead)
{
byte* data = new byte[1024];
UINT dw=myFile.Read(data, 1024);
sockRecv.Send(data, dw);
dwRead+=dw;
}
myFile.Close();
sockRecv.Close();
AfxMessageBox("发送完毕!");
return nRetCode;
}
现在应该可以运行了,然后根据你的需要修改
‘拾’ VC编写的文件传输程序中如何将SOCKET 作为参数传输
用指针传递,将A得地址传递过去,
CSocket 是一个类,占用一定内存,所以只能将内存的地址传递过去,不能将整个类传递过去,
这种问题很常见,建议你多看看别人的代码,就会了解到这些技巧
void B(CSocket* lpA)
{
lpA->Connect(...);
}
类似如上方法,调用时候使用
B(&A);
需要注意的是指针类型调用子过程是 -> 不是 .