Sockets FAQ/Tutorial
http://forums.wxwidgets.org/viewtopic.php?t=2736
有关志愿者翻译事务,请参见 对wx论坛的中文版块的展望
谢谢您的支持与参与!

我来翻译。翻译完了发在哪?这里还是Ryan Norton的帖子后面?Utensil wrote:征求志愿者翻译
Sockets FAQ/Tutorial
http://forums.wxwidgets.org/viewtopic.php?t=2736
有关志愿者翻译事务,请参见 对wx论坛的中文版块的展望
谢谢您的支持与参与!
Code: Select all
// 建立一个服务端socket wxSocketServer.... 如果出错返回NULL
// nPort 是端口号(例如:HTTP是80, FTP常用21等等)
wxSocketServer* wxCreateMyServerSocket(int nPort)
{
//
// 为端口(nPort)创建一个地址。
// 只有在你指定的端口号特别不常用时才失败。
//
wxIPV4address addr;
if(!addr.Service(nPort))
return NULL;
//
//为刚才创建的地址创建一个服务端socket
//用if语句判断是否创建成功
//
wxSocketServer* pServerSocket = new wxSocketServer(addr);
//
// 是否成功创建?
//
if (!pServerSocket->Ok())
{
//
// 如果因为端口已经被占用而失败则用一个消息框显示
// 其他情况直接返回
//
if (pServerSocket->LastError() == wxSOCKET_INVPORT)
wxMessageBox(wxT("Port in use!"));
pServerSocket->Destroy();
return NULL;
}
//
// 如果成功则返回创建成功的服务端socket指针!
//
return pServerSocket;
}
Code: Select all
//
// 通常情况是利用一个循环来接收
// 是一个bool值用来控制循环
// 当bServeClients被赋予false值时循环停止
//
while ( bServeClients )
{
//
// 调用Accept方法
// 前面提到过,这回挂起主线程直到有客户端被接受到
//
wxSocketBase * pSocket = pServerSocket->Accept();
//
// 如果pSocket的值是NULL那表示出错了,我们需要用break跳出循环。
//
if ( !pSocket )
break;
//
// OnClientConnect(pSocket)是一个你自己定义的函数
// 用来处理读/接收和写/发送等操作
//
OnClientConnect(pSocket);
//
// 注销客户端socket指针pSocket
//
pSocket->Destroy();
}
//
// 注销服务端socket指针pServerSocket
//
pServerSocket->Destroy();
Code: Select all
//
// 用事件句柄pHandler为服务端socket指针pServerSocket建立事件
//
void wxMySetupSocketEvents(wxSocketServer* pServerSocket,
wxEvtHandler* pHandler)
{
// 用wxASSERT_MSG确保pHandler是一个有效的句柄
wxASSERT_MSG(pHandler != NULL || wxTheApp != NULL,
wxT("NO EVENT HANDLER!"));
//
//如果句柄值为null我们可以用wxTheApp来处理事件
//
if (pHandler == NULL)
pHandler = wxTheApp;
//
//设置事件句柄为ID_SERVER
//
pServerSocket->SetEventHandler(*pHandler, ID_SERVER);
//
//指定和连接我们想接收的事件类型
//发送服务端事件到wxMyServer::OnServerEvent
//发送客户端事件到wxMyServer::OnSocketEvent
//
pHandler->Connect(ID_SERVER, wxEVT_SOCKET,
(wxObjectEventFunction) &wxMyServer::OnServerEvent );
pHandler->Connect(ID_SOCKET, wxEVT_SOCKET,
(wxObjectEventFunction) &wxMyServer::OnSocketEvent );
//
//基本上只有几类事件我们可以从服务端接收,
//通常我们只是连接事件就行了。
//
pServerSocket->SetNotify(wxSOCKET_CONNECTION_FLAG);
//
// 告诉服务端我们准备好接收事件了
// (其他类不需要这样,这是wxSockets类的一个专利)
//
pServerSocket->Notify(true);
}
Code: Select all
void wxMyServer::OnServerEvent(class wxSocketEvent& evt)
{
//我们只注册了连接事件
//所以确保我们接收的事件类型为wxSOCKET_CONNECTION
wxASSERT(evt.GetSocketEvent() == wxSOCKET_CONNECTION);
//
// 得到服务端socket
//
wxSocketServer* pServerSocket = (wxSocketServer*) evt.GetSocket();
//
//调用Accept方法,但由于我们知道将得到一个socket所以我们告诉他不要阻塞
//
wxSocketBase * pSocket = pServerSocket->Accept(false);
//
// 如果由于某种意外pSocket的值是null那么退出
//
if(!pSocket)
return;
//
// 设置客户端事件
// 已经为服务端调用了Connect方法,所以我们不需要在这里调用它了
//
pSocket->SetEventHandler(*((wxEvtHandler*)this), ID_SOCKET);
//
// 接收输入事件,这表明socket已准备好了读写等操作
// Lost事件意味着客户已从我们的服务端断开
// 我们需要注销Socket
//
pSocket->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
//
// 调用Notify表明我们已经准备好了接收客户端socket事件
//
pSocket->Notify(true);
}
Code: Select all
void wxMyServer::OnSocketEvent(class wxSocketEvent& evt)
{
//
// 测试事件为我们注册的类型
//
wxASSERT(evt.GetSocketEvent() == wxSOCKET_INPUT ||
evt.GetSocketEvent() == wxSOCKET_LOST);
//
// 获得客户端socket
//
wxSocketBase* pSocket = evt.GetSocket();
//
// 如果我们得到一个输入事件,这意味着我们可以通过这个客户socket读/写
//
if (evt.GetSocketEvent() == wxSOCKET_INPUT)
{
//
// 只注册Lost事件
// 我们不再对输入事件作响应
//
pSocket->SetNotify(wxSOCKET_LOST_FLAG);
//
// 和Accept例子一样
// 这是个你自己定义的函数用来从客户端socket读/写等.
//
OnClientConnect(pSocket);
}
//
// 注销客户端socket
//
pSocket->Destroy();
}
Code: Select all
class wxMyServerThread : public wxThread
{
wxMyServer* m_pServer; //服务端socket
wxSocketBase* m_pSocket; //客户端socket,用来读写
public:
wxMyServerThread(wxMyServer* pServer, wxSocketBase* pSocket) :
m_pServer(pServer), m_pSocket(pSocket) {}
~wxMyServerThread() { }
virtual ExitCode Entry()
{
//
// 还记得上面例子中的wxMyServer::OnSocketEvent方法吗?
// 和那里一样。我们在这进行读写socket的操作。
// 要记得你是在使用多线程所以要注意线程安全
//
m_pServer->OnClientConnect(m_pSocket);
//
// 在使用完客户端socket后注销它。
//
m_pSocket->Destroy();
return 0;
}
};
Code: Select all
void wxMyServer::OnSocketEvent(class wxSocketEvent& evt)
{
//
// 检测我们注册过的事件
//
wxASSERT(evt.GetSocketEvent() == wxSOCKET_INPUT ||
evt.GetSocketEvent() == wxSOCKET_LOST);
//
// 获得客户端socket
//
wxSocketBase* pSocket = evt.GetSocket();
//
// 如果我们得到一个输入事件那意味着我们可以向这个客户端socket里读或写了
//
if (evt.GetSocketEvent() == wxSOCKET_INPUT)
{
//
// 只注册Lost事件,因为我们不再输入了
//
pSocket->SetNotify(wxSOCKET_LOST_FLAG);
//
// 创建和运行线程
// 我们不需要使wxMyServerThread成为类成员变量
// 因此在结束时wxThread会自动注销它自己当然你也可以手动注销
//
wxMyServerThread* pThread =
new wxMyServerThread(this, pSocket);
pThread->Create();
pThread->Run();
}
else
{
//
// 当不再用客户端socket后注销它。
// 但我们只针对Lost事件这么做。
// 我们在线程最后针对读写事件注销socket。
//
pSocket->Destroy();
}
}
Code: Select all
bool MyApp::OnInit()
{
//这允许我们在第二个线程中用wxSocket
wxSocketBase::Initialize();
//...
return true;
}
Code: Select all
wxFile * uf=new wxFile(path,wxFile::write);
cloud_oper->Read(buffer,rs);
rs = uf->Write(buffer,rs);
if(uf->Error())
{
wxMessageBox(_("传输数据中止!"),_("Error"));
uf->Close();
cloud_oper->Close();
delete uf;
delete cloud_oper;
return false;
}
用wxFFile试试,打开模式用"wb".范家兵 wrote:各位兄弟们,能不能帮我看看这个问题。
最近用wxSocket和wxFile写了一个上传和下载文件的程序,可是上传完文件后再下载下来后,文件的大小是对的,而且TXT的文件是正常的。但是打开其他的文件时
就会报错说文件被破坏了。
服务器是64为的linux,客户机是32位的winXPCode: Select all
wxFile * uf=new wxFile(path,wxFile::write); cloud_oper->Read(buffer,rs); rs = uf->Write(buffer,rs); if(uf->Error()) { wxMessageBox(_("传输数据中止!"),_("Error")); uf->Close(); cloud_oper->Close(); delete uf; delete cloud_oper; return false; }