|
Well, I've done some TCP socket programming in the past but haven't used the CAsyncSocket class. What is interesting for me is that listen() returns EWOULDBLOCK for you. listen() should never return EWOULDBLOCK if you take a look at its documentation. listen() is always blocking but only for a very short time, it either returns failure or does its job (establises incoming connection request queue, the backlog) and returns with success.
So whats wrong with your code? Here is my guess: After starting the listen you unnecessarily issue some other request on your listen socket (for example an accept() call) and that results in a WSAEWOULDBLOCK message that is not still not the end of the world, but strange and you should check out the reason for this. About the WSAEADDRINUSE problem: If your listening starts as expected then it allocates and uses a port on your machine. When you connect the client side should issue a connect() call that results in the following events: your server side receives an event and as a result calls accept(). Both the server side accept() call and the client side connect() call returns a socket that has random ports assigned. HOWEVER: If your misterious CAsyncSocket class calls bind() before the connect() call, then it will fix the port of the returned socket by the connect() call and if that is the same as the port on which your server is listening then the socket can not be created on the client side! You should make sure that bind isn't called before connect() allowing the connect() call to assign a random port for the client side socket! bind() is usually used before connect when your firewall allows only specific ports for the software to communicate.
Another side note: WSAEADDRINUSE might return if you shut down your program during debugging. In this case some of your sockets might stay alive inside the network subsystem because of lingering. In this case sometimes you have to wait for minutes for that socket object to diminish from the network subsystem so as to release your ports.
|
|
|
|
|
Oops. It is the Accept() that returns the would block WSA code, not Listen. My appologies.
Here are some code fragments:
Omitting the error checking and reporting, the server initialize does this
bool C_Server::Class_Initialize()
{ ...
m_winsock_status = AfxSocketInit();
...
m_winsock_status = Create( m_port_number, SOCK_STREAM,
FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
DEFAULT_IP_ADDRESS ); ...}
the Listen() method does this:
bool C_Server::Class_Listen()
{
m_winsock_status = Listen();
... }
And the Accept() looks like this:
bool C_Server::Class_Accept()
{
mp_C_Server_Send_Time_Socket = new C_Server_Send_Time_Socket;
m_winsock_status = Accept( *mp_C_Server_Send_Time_Socket );
...}
I have continued work and am partway through the Client code. The client initialize seems to be OK, the client Connect() gets WSA code 10035, socket in use. I am beginning to think that is to be expected.
Advice?
Thanks for your time
Edit, I keep messing with the formatting trying to get the code blocks to display correctly. Having some difficulties there. Preview looks good, but when I post it does not. I think I have it, disabled the checkbox to treat my content as plain text. But this darn edit box keeps jumping around in the text.
|
|
|
|
|
You say you have problems with connecting and you copy paste everything here except the client code and connect. First go and check whether you (or your CAsyncSocket class) issue a bind() call to the client socket before the connect call.
|
|
|
|
|
[QUOTE]First go and check whether you (or your CAsyncSocket class) issue a bind() call to the client socket before the connect call.[/QUOTE]
No it does not. So it should Call the Bind in the Client before the Connect?
Thanks for your time
Edit: What is the code to mark a quote?
Edit: according to an MSDN page, Create() calls socket and if sucessful calls Bind. If it calls Bind, why should I explicitly call bind.
http://msdn.microsoft.com/en-us/library/xz019029(v=vs.80).aspx[^]
|
|
|
|
|
No it shouldnt call bind because that could cause WSAEADDRINUSE as I described previously.
|
|
|
|
|
Well then, I think I was doing things out of order. My dialog has all the pieces broken out so I performed the following steps:
Server::Initialize, wsa = 0
Client::Initialize, wsa = 0
Server::Listen, wsa = 0
Client::Connect wsa = 10035
Client::OnConnect() is called
Server::OnAccept() is called
Client::OnSend() is called
As noted earlier, I have all those methods defined but with no body and a breakpoint in each. Is this normal behavior? If so,...
Does Client::OnConnect() need to do anything?
Same for Server::OnAccept and Client::OnSend?
I am getting close. Next Step?
Thanks for your time
Edit again: I have this code in the function C_Server::Class_Accept() that is called via a button in the dialog.
bool C_Server::Class_Accept()
{
mp_C_Server_Send_Time_Socket = new C_Server_Send_Time_Socket;
m_winsock_status = Accept( *mp_C_Server_Send_Time_Socket );
}
Now I that I see C_Server::OnAccept() called, that code should be moved into the OnAccept method and executed automatically after the client connects. Then I would NOT have a manually called Accept() method in the server class.
Does that sound right?
modified 16-Sep-12 20:16pm.
|
|
|
|
|
There are numerous versions of the basic copy function, too many now. some of the new versions are declared safer because they incorporate a limiting count value. However, all the ones I have tried and inadvertenly tested just crash the application. I find that rather rude.
Are there any versions of ...cpy...() and ...printf...() that limit the count of characters copied to the space found in the destination string. Without an ungracefull app crash?
Thanks for your time
|
|
|
|
|
bkelly13 wrote: Are there any versions of ...cpy...() and ...printf...() that limit the count of
characters copied to the space found in the destination string.
Without an ungracefull app crash?
Unfortunately, No. Strcpy and printf are two of the most common functions that hackers use to exploit programming errors to "hack" into a program. When using these functions you need to pay extra attention to the size of your memory buffers and the actions you are performing on them.
You may have better luck with the C++ Standard Library.
The std::string class will manage your memory buffers, copies and concatenations.
std::cout doesn't have the program crash issues that you are running into.
All of my software is powered by a single Watt.
|
|
|
|
|
In that case I wish to go on record as saying that we need a new set of these functions. These functions should be named ...strcpy_l(...) and ...printf_l(...), with the "l" (lower case L) standing for Limited. Under the covers, the function will examine the destination, determine the length of the destination, and quietly refuse to move more characters than the destination string can hold.
Thanks for your time
|
|
|
|
|
I misunderstood part of your question.
There are these two functions:
strncpy(pDest, pSrc, size)
and
snprintf(pDest, count, pFormatStr, ...)
These will do what you are asking. Read the descriptions though, strncpy will not NULL terminate your string if it can't write all of the data to the buffer. This would open yourself up to another set of possibilities to crash your program.
All of my software is powered by a single Watt.
|
|
|
|
|
Those sound like an improvement, but I claim both are defective. If they leave the string in an known improper state, then that is a serious problem.
Thanks for your time
|
|
|
|
|
I think both strncpy() and snprintf() sucks. Once I searched for hours for a bug that was caused by strncpy(). Here is the problem: strncpy() is suboptimal because even if you copy a 1 byte string, it fills the whole remaining part of the destination buffer with zeros unnecessarily, and on the other hand it doesn't zero terminate the string if its length equals to or bigger than the size of the dest buffer. The missing zero terminator character in similar cases is true for snprintf() too. I highly discourage everyone from using these functions.
|
|
|
|
|
bkelly13 wrote: In that case I wish to go on record as saying that we need a new set of these functions. It's no good making statements like this on CodeProject, you need to go and complain to the standards body.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
|
I did make a suggestion as to how you may alleviate this in my answer to your previous question.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Here is my opinion: strcpy is totally useless and totally unsafe. Use a string class in C++ and assign one string to another instead of strcpy. You can even implement refcounting if you write your own string class and then assignment will be super fast. You can of course use std::string for your needs.
If you write you own string class or if you extend your own string class from std::string then you can put in a format and vformat function (similarly to the MFC CString class) and you can do formatting so that the buffer size will be managed automatically for you. Here is an example to that: How to Format a String[^]. I would mention only one thing regarding this formatting function in the link: The use of the std::vector is unnecessary, you could put the string formatting directly to the string. even in that case the string resizing unnecessarily fills the whole string with a fill character before formatting the string into its buffer. With a custom string you can write more optimal code for this task.
The type safety of format parameters with the vararg nature of format functions is still endangering your program. Using the bad parameter types make your program crash at runtime when the formatting code gets executed. Example to a buggy formatting statement: format("Name: %s\n", 5) . Gcc has an __attribute__ format printf to defend against such mistakes at compile time. You can mark you format function with this attribute and then gcc will catch such errors, it would find out for exmple that "%s" and 5 are not compatible. Unfortunately visual C++ doesn't have such feature but our current project is crossplatform so we compile it with both VC++ and gcc and this gcc feature is priceless.
Unfortunately this kind of formatting is too widespread and comfortable without similarly comfortable alternatives so this wont be dropped easily from C++. However a feature like the one gcc has can make this stuff quite usable and safe.
|
|
|
|
|
You could try something like Boost's format[^] library.
Steve
|
|
|
|
|
Environment: Windows 7, Visual Studio 2008, MFC, CPP
Goal: start with an int, and put the character string equivilant into a text format such that a static control variable from a dialog will accept it. mp_C_Client is a pointer to a class that contains the TCP/IP code. The error code is returned as expected.l
void C_MFC_Winsock_01_Dlg::OnBnClickedBtnClientInit()
{
bool method_status = false;
int wsa_error_code = 0;
TCHAR wsa_error_text[ 16 ];
mp_C_Client = new C_Client;
if( mp_C_Client != NULL )
{
method_status = mp_C_Client->Class_Initialize();
wsa_error_code = mp_C_Client->Class_Get_WSA_Error_Code();
wprintf( wsa_error_text, "%d", wsa_error_code ); m_client_wsa_error_text.SetWindowText( wsa_error_text );
}
Intellisense shows the control variable argument as:
m_client_wsa_error_text.SetWindowText( LPCTSTR lpszstring )
This compiles but after the wprintf the text in wsa_error_text is not as expected.
How should this be coded?
Thanks for your time
Edit: This post looked pretty good in the preview, but not good after I posted it.
And again: But now its okay. ????
|
|
|
|
|
bkelly13 wrote: wprintf( wsa_error_text, "%d", wsa_error_code ); You should be using _stprintf() [^] to format the string into a buffer.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
That got me where I needed to go. I used this:
int wsa_error_code;
TCHAR wsa_error_text[ 16 ];
...
_stprintf_s( wsa_error_text, 15, L"%d", wsa_error_code );
Note the _s on the end and the L prefixing the "%d"
This nonsense with all the different character types is way out of hand. After I get over this hurdle of writing some async TCP/IP code, I think I should re-create the project and get rid of all the multibyte and unicode nonsense.
Thanks for your time
Edit: The post was nicely formated in the preview, but looks bad after being submitted.
|
|
|
|
|
Unicode is the default compile type for Visual Studio projects.
If you would like to work in multi-byte only, you can change that property in your compiler settings on the General page.
The _stprintf_s function compiles using the character format based on that compiler setting.
If you don't want to mess with the compiler settings, you can use a char rather than a TCHAR, and the function sprintf_s,
or if you want to force the unicode type use the data type wchar_t, and the function wsprintf_s.
All of my software is powered by a single Watt.
|
|
|
|
|
bkelly13 wrote: Note the _s on the end and the L prefixing the "%d" The _s is a good thing as it helps to protect against buffer overflow, but less critical when you are sure that your buffer is big enough. The L prefix on your string is wrong, however, as you are using TCHAR so your buffer could be ASCII or Unicode. You should use the _T() macro around your strings, and the _countof() macro to specify the size thus:
TCHAR wsa_error_text[ 16 ];
...
_stprintf_s( wsa_error_text, _countof(wsa_error_text), _T("%d"), wsa_error_code );
Alternatively make your project all ASCII or all Unicode.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Cool, thanks for the aditional info.
I looked up _countof and discovered the return type is not declared anywhere. Is it an int, unsigned int, size_t, or something else?
The _countof function does not accomodate the null that belongs at the end of a character string. That is important because,...
The various versions of ...printf...( destination, count, source ) that I have tried appear to put a limiting number on the count of characters transferred. However, that limit takes the form of a program crash. Downright nasty! Just as bad as ASSERT.
IMNSHO, these functions should use the count argument to limit the number of characters being transfered rather than crashing the program. Do any of these "safe", or maybe "less dangerous" functions simply limit the number of character moves rather than crashing the app?
( BTW: In My Not So Humble Opinion )
Thank you for taking the time to reply.
|
|
|
|
|
bkelly13 wrote: I looked up _countof and discovered the return type is not declared anywhere. If you look closely you will see that it is a macro which invokes the sizeof() operator, so it returns the same type as that.
bkelly13 wrote: The various versions of ...printf. The functions with the _s suffix and the buffer length parameter will avoid the crash by giving you an error return or ASSERT if you attempt to overwrite the buffer, so these functions should always be used for safety. The old "unsafe" versions are part of the base C libraries and remain for backwards compatibility. As you so rightly say, they should not be used any more.
You can trap any ASSERT s that may be raised by adding your own handler as described here[^].
It always pays to read the documentation (including any linked pages) thoroughly. Not that I do so very often.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
dose any one know how to mirror system image list , iam developing RTL application on LTR windows xp , so i want to mirror image before setting listctrl so it will not look upside down ,
her what i did so far and i failed :
CMFCToolBarImages toolBarImage;
SHFILEINFO sfi;
UINT nFlags = SHGFI_SYSICONINDEX | SHGFI_ICON ;
HIMAGELIST hIL = (HIMAGELIST)SHGetFileInfo(szWindows, 0, &sfi, sizeof(sfi), nFlags);
CImageList* list = CImageList::FromHandle(hIL);
HBITMAP bitmap = list->GetImageWell();
toolBarImage.MirrorBitmap(bitmap,32);
any idea or small hint will be appreciated ?
asdasda
|
|
|
|