🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Winsock with Visual Basic

Started by
20 comments, last by Zipster 22 years, 8 months ago
Ok, so I''m trying to make a simple Winsock program that just sends and recieves data from an already existing server. Using the UDP protocol, I just send four bytes of 255 (integer -1), followed by a string command w/ NULL terminator, and the server is supposed to send me back information. Yeah, well the latter isn''t happening. I have the following code for my form:
  
'' The name of the Winsock control is, *gasp* Winsock
With Winsock
        .Bind 1010
        
        .RemoteHost = IP.Text ''IP is a textbox control
        .RemotePort = Val(Port.Text) ''Another textbox control
    
        .SendData -1
        .SendData "info"
End With
  
I then set up my Winsock_DataArrival function to just pop a message box if it recieves data. Is there something I am doing wrong? I know the actual process works, because I have a simple C-console application that uses Winsock to send the exact same data to the exact same IP and the exact same port! Only the server actually responds to that program
Advertisement
Why are you calling Bind? I don't think that is necessary. From MSDN:

---
To transmit data, first set the client computer's LocalPort property. The server computer then needs only to set the RemoteHost to the Internet address of the client computer, and the RemotePort property to the same port as the client computer's LocalPort property, and invoke the SendData method to begin sending messages. The client computer then uses the GetData method within the DataArrival event to retrieve the sent messages.
---

I don't see you setting the "LocalPort" property. Maybe "Bind" does this for you... but then maybe not.


Edited by - Pyabo on October 10, 2001 6:39:27 PM
-> Just bind a udp socket if you wanna listing for incoming data
-> As client you have to set remote port and ip, localport
is just needed as server (for listing)
-> Never use the lame vb winsock control, use
winsock2 api with event objects or bsd select function
-> Never use Vb
-> ...



get the next c++ compiler and put something like
this in ( u have to startup winsock of course )


printf("\nDatagram Client sending to server: %s on port: %d",
szServer, nPort);

// Find the server
LPHOSTENT lpHostEntry;

lpHostEntry = gethostbyname(szServer);
if (lpHostEntry == NULL)
{
error...
return;
}

SOCKET theSocket;
theSocket = socket(AF_INET,
SOCK_DGRAM,
IPPROTO_UDP);
if (theSocket == INVALID_SOCKET)
{
error ...
return;
}

SOCKADDR_IN saServer;
saServer.sin_family = AF_INET;
saServer.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);
cout << saServer.sin_addr << endl;
saServer.sin_port = htons(nPort);

char szBuf[256];
int nRet;

strcpy(szBuf, "From the Client");
nRet = sendto(theSocket,
szBuf,
strlen(szBuf),
0,
(LPSOCKADDR)&saServer,
sizeof(struct sockaddr));
if (nRet == SOCKET_ERROR)
{
error...
closesocket(theSocket);
return;
}

// Wait for the reply
memset(szBuf, 0, sizeof(szBuf));
int nFromLen;

nFromLen = sizeof(struct sockaddr);
recvfrom(theSocket,
szBuf,
sizeof(szBuf),
0,
(LPSOCKADDR)&saServer,
&nFromLen);

if (nRet == SOCKET_ERROR)
{
error...
closesocket(theSocket);
return;
}

// Display the data that was received
printf("\nData received: %s", szBuf);

closesocket(theSocket);
I think he is calling bind because he is using UDP. Typically clients should not call bind as Connect() will do this implicitly for you.

Could it be that the server isn''t receiving your data since you are using UDP? BTW I''m not sure your NULL terminator is being sent. I''m not sure if during the conversion from a UNICODE string (BSTR) to a ANSI string if the terminator gets included. You may need to add the null-terminator manually:

"info" + Chr(0)

Though I''m not sure how that will work. The other option is to copy the string into an array of bytes before sending, then the underlying Winsock Control doesn''t have the string (I believe).

Remember SendData takes a VARIANT data type which requires conversion to a byte array before being sent on the network.

Dire Wolf
www.digitalfiends.com
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
quote: Why are you calling Bind? I don''t think that is necessary. From MSDN:

---
""""
---

I don''t see you setting the "LocalPort" property. Maybe "Bind" does this for you... but then maybe not.


I don''t know what you are looking at, but my MSDN tells me to call Bind on it to setup a UDP peer, which is what I am doing; this specifically:

quote:
UDP Basics
Creating a UDP application is even simpler than creating a TCP application because the UDP protocol doesn''t require an explicit connection. In the TCP application above, one Winsock control must explicitly be set to "listen," while the other must initiate a connection with the Connect method.

In contrast, the UDP protocol doesn''t require an explicit connection. To send data between two controls, three steps must be completed (on both sides of the connection):

1. Set the RemoteHost property to the name of the other computer.


2. Set the RemotePort property to the LocalPort property of the second control.


3. Invoke the Bind method specifying the LocalPort to be used. (This method is discussed in greater detail below.)


So LocalPort isn''t even used except if you want to pass it to Bind.


Also, I assumed that using the quotes around the string automatically implied the NULL terminator... or is that just C/C++? I tried doing this too:
  .SendData -1.SendData "info".SendData 0  

But that didn''t work. I think there has to be a problem with the way I''m sending the data, but I don''t know what other ways there are to send it!!!

And like I said, I want to make this VB; I want a nice Windows interface behind it, and I don''t think I''m adding enough code to justify turning it into a MFC application, but on the flipside, I''m adding enough things to make using the normal Windows API a real hastle So VB it is! And look at that ugly Winsock code! That''s what my console application looks like
Damn, I just figured it out! I tried doing this:
  .SendData Chr(255) + Chr(255) + Chr(255) + Chr(255) + "info"  

And the server finally responded! I find that quite frusterating, since I also tried sending four 255 bytes as seperate SendData calls before, and it didn''t work. I also don''t know why it wouldn''t convert -1 into four bytes of 255 for me automatically... oh well it works now
Ok, now it''s being gay! I know what kind of information the server is going to return, but the GetData procedure is in flexable as hell! I know the server is going to send me one integer, folowed by a byte, five strings, and then three more bytes. But GetData automatically assumes I want to get the ENTIRE buffur in one call, which is really pissing me off, because I want to be able to call it with maxLen set to the number of bytes I want, and then have it advance that number of bytes into the buffer so I can keep parsing! For example, I read in the first integer and byte, get the strings, then toss the last three bytes. But it doesn''t work that way... my last resort is to get all the data in one big string and split it up myself, but that''s real bull and I was hoping there might be some other way.
Maybe using an bytearray? You know an integer is two bytes, a long 4, etc. the only problem would be a string. But since you know the layout of your packets you could simply add a byte/integer that gives the length of the string... that''s why in DP there is difference between GetDataFromBuffer and GetStringFromBuffer, I think..
www.persistentrealities.com for Inline ASM for VB, VB Fibre, and other nice code samples in C++, PHP, ASP, etc.<br/>Play Yet Another Laser Game!<br/>
An integer would be 4 bytes in 32-bit systems.

The problem with the .GetData procedure is that it assumes I want the entire data buffer in one call , so it tries to stuff all the data into the first integer variable I pass with the first GetData call, and I get an error saying the datagram overflows the variable, which would be true!
Remember, it''s a Visual Basic integer...

Private Sub Form_Load()    Dim intValue As Integer    MsgBox "Integer in bytes: " & LenB(intValue)End Sub 

www.persistentrealities.com for Inline ASM for VB, VB Fibre, and other nice code samples in C++, PHP, ASP, etc.<br/>Play Yet Another Laser Game!<br/>

This topic is closed to new replies.

Advertisement