经过大量调查,我无法真正找出问题所在。这台机器不会使用 SQLBrowseConnect 发现它自己的 SQL 实例。因此,我决定编写自己的版本。发现 SQL 实例非常容易。您只需将广播 UDP 数据包发送到端口 1434,其中包含有效负载 0x02(1 个字节)并等待 SQL 服务器响应。它们以每个服务器的一个数据包响应,其中详细说明了该机器上的所有实例。执行此操作所需的代码如下所示:
// to enumerate sql instances we simple send 0x02 as a broadcast to port 1434.
// Any SQL servers will then respond with a packet containing all the information
// about installed instances. In this case we only send to the loopback address
// initialise
WSADATA WsaData;
WSAStartup( MAKEWORD(2,2), &WsaData );
SOCKET udpSocket;
struct sockaddr_in serverAddress;
if ((udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
return;
}
// set up the address
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
serverAddress.sin_port = htons(1434);
// the payload
char payload = 0x02;
// config the port for broadcast (not totally necessary right now but maybe in the future)
BOOL broadcast = TRUE;
setsockopt(udpSocket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<const char*>(&broadcast), sizeof(BOOL));
// receive address info
sockaddr_in RecvAddr;
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof (SenderAddr);
// bind the socket to the receive address info
int iResult = bind(udpSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
if (iResult != 0)
{
int a = WSAGetLastError();
return;
}
if (sendto(udpSocket, &payload, 1, 0, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0)
{
int a = WSAGetLastError();
return;
}
// set up a select so that if we don't get a timely response we just bomb out.
fd_set fds ;
int n ;
struct timeval tv ;
// Set up the file descriptor set.
FD_ZERO(&fds) ;
FD_SET(udpSocket, &fds) ;
// Set up the struct timeval for the timeout.
tv.tv_sec = 5 ;
tv.tv_usec = 0 ;
// Wait until timeout or data received.
n = select ( (int)udpSocket, &fds, NULL, NULL, &tv ) ;
if ( n == 0)
{
// timeout
return;
}
else if( n == -1 )
{
// error
return;
}
// receive buffer
char RecvBuf[1024];
int BufLen = 1024;
memset(RecvBuf, 0, BufLen);
iResult = recvfrom(udpSocket,
RecvBuf,
BufLen,
0,
(SOCKADDR *) & SenderAddr,
&SenderAddrSize);
if (iResult == SOCKET_ERROR)
{
int a = WSAGetLastError();
return;
}
// we have received some data. However we need to parse it to get the info we require
if (iResult > 0)
{
// parse the string as required here. However, note that in my tests, I noticed
// that the first 3 bytes always seem to be junk values and will mess with string
// manipulation functions if not removed. Perhaps this is why SQLBrowseConnect
// was having problems for me???
}