Thread View: borland.public.cppbuilder.internet.socket
7 messages
7 total messages
Started by Mark Jacobs
Tue, 06 Jun 2006 10:36
BDS2006 requires WSAStartup be called...
Author: Mark Jacobs
Date: Tue, 06 Jun 2006 10:36
Date: Tue, 06 Jun 2006 10:36
73 lines
3294 bytes
3294 bytes
The following works correctly under BCB5. Virgin BCB2006 VCL project, drop a
button onto the form :-
//--HEADER FILE------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <WSockets.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//--SOURCE FILE------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
struct hostent *mhstj; struct in_addr mjinad;
unsigned long eha; int ii=0; AnsiString cret;
mhstj=gethostbyname("");
if (!mhstj)
{
ShowMessage("Socket Error "+AnsiString(WSAGetLastError()));
return;
}
cret=AnsiString(mhstj->h_name);
while (mhstj->h_addr_list[ii])
{
memcpy(&mjinad,mhstj->h_addr_list[ii++],sizeof(in_addr));
cret+="\n"+AnsiString(inet_ntoa(mjinad));
}
ShowMessage("Hello - Your IP Details are :-\n"+cret);
}
//---------------------------------------------------------------------------
In BCB5 I get the IP details as expected. In BDS2006 error 10093 is returned
implying something about WSAStartup not being called. Having looked at the
structure required to set up a call to WSAStartup, I am not happy. Why doesn't
this work as is?
--
�
Mark Jacobs
DK Computing
http://www.dkcomputing.co.uk
Re: BDS2006 requires WSAStartup be called...
Author: Remy Lebeau (TeamB)
Date: Tue, 06 Jun 2006 16:42
Date: Tue, 06 Jun 2006 16:42
71 lines
3336 bytes
3336 bytes
"Mark Jacobs" <http://www.jacobsm.com/mjmsg?Borland%20Newsgroup> wrote in
message news:44855a92$1@newsgroups.borland.com...
> mhstj=gethostbyname("");
To get the local IP, you should be using gethostname() instead of
gethostbyname("").
> memcpy(&mjinad,mhstj->h_addr_list[ii++],sizeof(in_addr));
> cret+="\n"+AnsiString(inet_ntoa(mjinad));
You don't need to copy the address before converting it. You can convert
the original value directly:
cret += "\n" + AnsiString(inet_ntoa(* (in_addr*)
mhstj->h_addr_list[ii++]);
> In BCB5 I get the IP details as expected. In BDS2006 error
> 10093 is returned implying something about WSAStartup not
> being called.
As well it should be. You have to call WSAStartup() before calling any
other socket-related functions. You should be doing that in any version of
BCB. If BCB 5 is not requiring you to do that, then you likely have a
package installed that is calling WSAStartup() automatically during its
initialization. You should not be relying on that behavior in your own
code. Always explitically call WSAStartup() and WSACleanup() in any socket
code that you write yourself.
> Having looked at the structure required to set up a call to WSAStartup, I
am not happy.
You don't need to set up anything in order to call WSAStartup(). It only
has 1 input parameter, the requested version. The WSADATA structure is an
output parameter so that you know which version is actually being used,
which may be different than the version you request. You can ignore the
structure if you are only going to be using socket operations that are
supposed all the way back to v1.0, ie:
bool WasInitialized = false;
__fastcall TForm1::TForm1(TComponent *Owner)
: TForm()
{
// can't use WSAGetLastError() with WSAStartup()...
WSADATA wsa = {0};
int ret = WSAStartup(MAKEWORD(1, 0), &wsa);
WasInitialized = ( ret != 0 );
if( !WasInitialized )
MessageBox(NULL, ("Startup Error " + AnsiString(ret)).c_str(),
"Error", MB_OK | MB_ICONERROR);
}
__fastcall TForm1::~TForm1()
{
if( WasInitialized )
WSACleanup();
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
//...
}
> Why doesn't this work as is?
Because it is not supposed to in the first place.
Gambit
Re: BDS2006 requires WSAStartup be called...
Author: Michel Leunen
Date: Tue, 06 Jun 2006 17:54
Date: Tue, 06 Jun 2006 17:54
17 lines
1616 bytes
1616 bytes
Mark Jacobs wrote: > #include <WSockets.hpp> Besides what Remy told you, this isn't the right header to include if you want to use sockets. #include <winsock.h> or <winsock2.h> instead. If I'm not mistaken, WSockets.hpp comes from the ICS components suite and you are not using one of these components in your sample. Michel -- ---------------------------------------- Michel Leunen mailto: see my homepage. C++Builder, BCC5.5.1 Web site: http://www.leunen.com/ ----------------------------------------
Re: BDS2006 requires WSAStartup be called...
Author: Remy Lebeau (TeamB)
Date: Tue, 06 Jun 2006 18:12
Date: Tue, 06 Jun 2006 18:12
20 lines
1623 bytes
1623 bytes
"Michel Leunen" <nospam@noreply.please> wrote in message
news:4485c157$1@newsgroups.borland.com...
> > #include <WSockets.hpp>
I didn't even catch that. In that case, my earlier statement:
"If BCB 5 is not requiring you to do that, then you *LIKELY* have a
package installed that is calling WSAStartup() automatically during its
initialization."
Should be changed to this instead:
"If BCB 5 is not requiring you to do that, then you *DEFINATELY* have a
[third-party] package [included in the project] that is calling WSAStartup()
automatically during its initialization."
Gambit
Re: BDS2006 requires WSAStartup be called...
Author: Mark Jacobs
Date: Wed, 07 Jun 2006 08:49
Date: Wed, 07 Jun 2006 08:49
14 lines
1468 bytes
1468 bytes
Remy Lebeau (TeamB) wrote: > You have to call WSAStartup() before calling > any other socket-related functions. What other functions would I have to use in order to require WSAStartup? What 3rd party VCL components use windows sockets? If there is a 3rd party library calling WSAStartup automatically, how can I identify which one it is? If WSAStartup has been called multiple times, how do oyu know how many times to call WSACleanup? -- � Mark Jacobs DK Computing http://www.dkcomputing.co.uk
Re: BDS2006 requires WSAStartup be called...
Author: Remy Lebeau (TeamB)
Date: Wed, 07 Jun 2006 17:37
Date: Wed, 07 Jun 2006 17:37
49 lines
3398 bytes
3398 bytes
"Mark Jacobs" <http://www.jacobsm.com/mjmsg?Borland%20Newsgroup> wrote in message news:4486930a@newsgroups.borland.com... > What other functions would I have to use in order to require WSAStartup? All of the socket-related functions require WSAStartup(). It initializes the calling thread to use the socket library. For example, one thing it does is to create the TLS slot (thread local storage) that WSAGetLastError() uses to store error codes. That is why WSAGetLastError() can't be used until after WSAStartup() returns a successful return value. If WSAStartup() fails, there is no guarantee that the TLS has been created. > What 3rd party VCL components use windows sockets? There are too many to list. There are large libraries, such as Indy, ICS, and Synapse. But there are numerous other component implementations that use sockets for other, more specialized, purposes. That is like asking "what third-party components use TWinControl". > If there is a 3rd party library calling WSAStartup automatically We've already covered that. The code you showed earlier is including an ICS header file. So ICS is the one calling WSAStartup() for its own purposes. > how can I identify which one it is? There is no straight-forward way to do that. Nor should you try to care about it. As I already told you earlier, just call WSAStartup() in your own code regardless of what the rest of the project is doing. It is perfectly safe to call WSAStartup() multiple times. Like any other API, WinSock is implemented as a DLL. Calling WSAStartup() multiple times will only load the DLL once the first time, and then increment its reference count on subsequent calls. Just make sure that you call WSACleanup() once for each successful WSAStartup() so that the reference count is balanced, otherwise the DLL will not be unloaded properly. > If WSAStartup has been called multiple times, how do oyu > know how many times to call WSACleanup? You have to call WSACleanup() once, and only once, for each successful call to WSAStartup() that you make. If you call WSAStartup() in your own code once, and it succeeds, then call WSACleanup() only once in your own code. Every other library/component that also calls WSAStartup() will be doing the same thing. You DO NOT call WSACleanup() in your own code for other people's calls to WSAStartup(). Gambit
Re: BDS2006 requires WSAStartup be called...
Author: Mark Jacobs
Date: Thu, 08 Jun 2006 10:24
Date: Thu, 08 Jun 2006 10:24
10 lines
1320 bytes
1320 bytes
Remy Lebeau (TeamB) wrote: ... Thanks a lot for your thorough explanations - I am now rewriting my code to be WSAStartup compliant. Thanks again, -- � Mark Jacobs DK Computing http://www.dkcomputing.co.uk
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads