I use wxSocketClient transmiss a file to wxSocketServer,when the file's length less than 8688 bytes,they work well,otherwise,wxSocketServer will read 8688 bytes at most.
So when transmiss a file which class should i use? wxSocketClient or wxSocketOutputStream/wxSocketInputStream ?
When wxSocket transmiss a file which class should i use? Topic is solved
When wxSocket transmiss a file which class should i use?
wx2.8.11
Win XP GCC 4.4.1/VC2005
Ubuntu 10.04 GCC 4.4.3
Win XP GCC 4.4.1/VC2005
Ubuntu 10.04 GCC 4.4.3
ok! I use wxThread in wxSocketClient,when drop files on wxTextCtrl,the thread will be run.
First i write 1 byte to tell wxSocketServer that 1 is a file,and then 4 bytes to tell wxSocketServer file'size,and then 50 bytes is the file's name,and last is file data that need to be saved.
here is the code that in wxSocketClient program:
When wxSocketServer receive socket event,it will start a new thread.
First it read 1 byte to know the type of socket data,and then 4 bytes to know the data length ,last is the data.
Here is the code that in wxSocketServer:
I use codeblocks wx2.8.11 unicode multi gcc dll .the project is in attachment.
First i write 1 byte to tell wxSocketServer that 1 is a file,and then 4 bytes to tell wxSocketServer file'size,and then 50 bytes is the file's name,and last is file data that need to be saved.
here is the code that in wxSocketClient program:
Code: Select all
void* SocketThread::Entry()
{
/*
his->m_arrFileName is the array that when drop files on wxTextCtrl
*/
for(size_t i=0; i<this->m_arrFileName.GetCount(); i++)
{
wxString filePath = this->m_arrFileName[i];//files path
wxString fileName = wxFileNameFromPath(filePath);//file name
const wxChar* pName = fileName.c_str();//wxChar* file name
wxFile file;
file.Open(filePath,wxFile::read);
size_t fileSize = file.Length();//file;size
wxUint8 type = 1;//1=>file,0=>text
wxMemoryBuffer memoryBuffer;
memoryBuffer.AppendData(&type,1);//append type
memoryBuffer.AppendData(&fileSize,4);//append file size
memoryBuffer.AppendData(pName,50);//append file name
wxUint8* buffer = new wxUint8[fileSize];
size_t len = file.Read(buffer,fileSize);//read file data into wxMemoryBuffe
memoryBuffer.AppendData(buffer,len);//append file data
size_t length = memoryBuffer.GetDataLen();//data'length that need to send
wxUint8* data = (wxUint8*)memoryBuffer.GetData();//data
this->m_socket->Write(data,length);//Write data to wxSocketServer
file.Close();
delete []buffer;
}
return NULL;
}
First it read 1 byte to know the type of socket data,and then 4 bytes to know the data length ,last is the data.
Here is the code that in wxSocketServer:
Code: Select all
void* SocketThread::Entry()
{
wxUint8 type;//type
this->m_socket->Read(&type,1);
if(type == 0)//text that should show on gui
{
size_t length;//wxChar length
this->m_socket->Read(&length,4);
wxChar* buffer = new wxChar[length/2];
this->m_socket->Read(buffer,length);
wxString s(buffer);
this->m_listCtrl->InsertItem(0,wxT(""));
this->m_listCtrl->SetItem(0,0,s);
//wxMessageBox(wxString::Format(wxT("Type: %d,Length: %d,Value: %s,Receive: %d"),type,length,s.c_str(),this->m_socket->LastCount()));
delete []buffer;
}
else if(type == 1)//a file
{
size_t length;//wxFile length
this->m_socket->Read(&length,4);
wxChar* pName = new wxChar[50/2];//file'name
this->m_socket->Read(pName,50);
wxString fileName(pName);//wxString file name
wxUint8* buffer = new wxUint8[length];//buffer
this->m_socket->Read(buffer,length);
wxFile file;//create a new file
file.Create(fileName,true);
file.Open(fileName,wxFile::write);
file.Write(buffer,this->m_socket->LastCount());
file.Close();
delete []buffer;
/*wxMessageBox(wxString::Format(wxT("Type: %d,Length: %d,FileName: %s"),type,length,pName));*/
delete []pName;
}
return NULL;
}
- Attachments
-
- wxSocket.zip
- (71.68 KiB) Downloaded 108 times
wx2.8.11
Win XP GCC 4.4.1/VC2005
Ubuntu 10.04 GCC 4.4.3
Win XP GCC 4.4.1/VC2005
Ubuntu 10.04 GCC 4.4.3
-
- Ultimate wxWidgets Guru
- Posts: 672
- Joined: Tue Aug 31, 2010 6:22 am
- Location: Belgium
Either you configure your socket in blocking mode (http://biolpc22.york.ac.uk/wx/docs/html ... sesetflags) or you should write a more complex code.
Your problem is that you fills the output buffer and the socket truncates the sent data. If you want to send everyting with a single command, you should configure your socket in blocking mode. But, in this case, the GUI will be blocked until everything is sent.
If you do not want the GUI to be blocked, you have to check how many bytes were sent (with wxSocketBase::LastCount) and send remaining data when there is space in output buffer.
Your problem is that you fills the output buffer and the socket truncates the sent data. If you want to send everyting with a single command, you should configure your socket in blocking mode. But, in this case, the GUI will be blocked until everything is sent.
If you do not want the GUI to be blocked, you have to check how many bytes were sent (with wxSocketBase::LastCount) and send remaining data when there is space in output buffer.
-
- Ultimate wxWidgets Guru
- Posts: 672
- Joined: Tue Aug 31, 2010 6:22 am
- Location: Belgium
-
- In need of some credit
- Posts: 1
- Joined: Thu Jan 13, 2011 4:42 pm
There is no guaranty that all of the data will show up at the same time.
You should be checking LastCount after every read to ensure that you actually did read some data.
In your type==1 condition you should do something like the following in place of
// this->m_socket->Read(buffer,length);
wxUint32 u32Rcvd = 0;
while (u32Rcvd < length)
{
this->m_socket->Read(buffer + u32Rcvd,length - u32Rcvd);
u32Rcvd += this->m_socket->LastCount();
// Maybe check for error here with this->m_socket->Error and LastError
// Maybe sleep a bit here to take load off cpu.
}
Hope this helps.
You should be checking LastCount after every read to ensure that you actually did read some data.
In your type==1 condition you should do something like the following in place of
// this->m_socket->Read(buffer,length);
wxUint32 u32Rcvd = 0;
while (u32Rcvd < length)
{
this->m_socket->Read(buffer + u32Rcvd,length - u32Rcvd);
u32Rcvd += this->m_socket->LastCount();
// Maybe check for error here with this->m_socket->Error and LastError
// Maybe sleep a bit here to take load off cpu.
}
Hope this helps.
Danny Scott