# VBForums CodeBank > CodeBank - Visual Basic 6 and earlier >  VB6 UniSock: winsock replacement [2008-08-14]

## Merri

This is my attempt in writing a Winsock class module. The major difference to other implementations is that there are no other files, it is just one class file. By syntax and behavior I've tried to make it imitate the Winsock control when it has made sense. The major syntax differences are the Close event (changed to *Closing*) and Close method (changed to *CloseSocket*). I have also adjusted the datatypes, so instead of variants there are more precise datatypes used when appropriate. This allows VB's autocomplete to work.

Unlike other implementations you can use a wide variety of arrays, even string arrays, for both getting and sending data. I've also paid attention in keeping the class efficient & lightweight. There are also small convenience features: many of the methods are now functions that return a boolean value.

The greatest difference to other Winsock implementations is a switch between binary mode and text mode. In text mode you are only able to process text data (ideal for entirely text based conversation, such as IRC). Text mode also disables DataArrival event and enables TextArrival event. Text mode's true power is in that it automatically processes incoming Unicode strings for you, namely UTF-8 and UTF-16. If you expect to receive Unicode data, you don't need to care about it. If you receive ANSI text in TextArrival, you must use StrConv or other method to process the string to displayable form.

I have done testing only with TCP. This means UDP portion of the code is untested. My tests even on TCP side aren't full scale, so if you run into any oddness I'd like to know about it.


A small sample project is included that demonstrates a continuously listening server, a client and a new socket accepted by server when the client connects. The code should be fairly well commented.

----------


## Merri

*Events*

Closing()
*Description*: Triggered when socket is about to close but has not yet been fully closed.

Connect()
*Description*: Triggered upon successful connection. Data may now be sent.

ConnectionRequest(RequestID)
*Description*: Triggered when a remote host is connecting to a listened port.

DataArrival(BytesTotal)
*Description*: Triggered when data has arrived in binary mode.

Error(Number, Description, sCode, Source, HelpFile, HelpContext, CancelDisplay)
*Description*: Triggered whenever an internal error occurs.

*NOTE*: Unlike Winsock control, an error does not prevent operation and you are not required to close the connection.

SendComplete()
*Description*: Triggered when sending data has finished.

SendProgress(BytesSent, BytesRemaining)
*Description*: Triggered as sending data progresses.

StatusChange(Status)
*Description*: Triggered when status changes. However, error status is not received in favor of Error event.

TextArrival(Text, LineChange, ANSI)
*Description*: Triggered when a line of data has arrived. If text is Unicode, Text can be used directly. If text is ANSI, you must use StrConv or other means to process the text into an usable string.


*Methods*

Accept(RequestID) Boolean
*Description*: Accepts a connection request from another UniSock control. The socket must be in a closed state before using this function. Upon successful accept Connect event is fired.

*Result*: Returns True if the RequestID was valid.

Bind([LocalPort], [LocalIP]) Boolean
*Description*: Binds socket to currently set local port and ip. These may also be given as parameters. LocalIP can be an IP or a hostname.

*Result*: Returns True if the IP and port were binded successfully.

CloseSocket() Boolean
*Description*: Cancels all asynchronous activity and closes the socket.

*Result*: Returns True if the socket was closed.

Connect([RemoteHost], [RemotePort]) Boolean
*Description*: If protocol is TCP, begins connection to currently set remote host and port, or given host and/or port. If protocol is UDP, the current local ip and port are bind.

*Result*: Returns True if the connection could be initialized (TCP) or True if the local ip and port could be bind (UDP).

GetData(Data, [VarType], [MaxLen]) Boolean
*Description*: Gets current incoming buffer to variable passed to Data. If passed variable is a variant, variable type set into optional VarType will be used. The default datatype is byte array. MaxLen sets the amount of bytes to retrieve. Whole buffer is retrieved if MaxLen is 0 or less, or greater than the buffer size.

Unlike other Winsock control/class implementations, you may use all numeric datatypes and string: Boolean, Byte, Currency, Date, Double, Integer, Long, Single and String. All supported datatypes can be also be passed as arrays. String array separator is automatically detected (CRLF, LF, CR or NullChar). Strings are coerced from ANSI.

*Result*: Returns True if the buffer was retrieved.

Listen() Boolean
*Description*: Binds currently set local ip and port if not bind already and starts listening for incoming connections. Upon connection ConnectionRequest event is fired.

*Result*: Returns True if binding and initializing listening was successful.

PeekData(Data, [VarType], [MaxLen]) Boolean
*Description*: Identical to GetData, except the data is not removed from the buffer.

SendData(Data) Boolean
*Description*: Sends the given data to remote host. See GetData for supported datatypes. Strings are coerced to ANSI.

*Result*: Returns True if inserting data to output buffer was successful.

SendText(Text, [TextFormat]) Boolean
*Description*: Sends a single line of string data. A line change character determined by LineChange is added to the string. TextFormat determines whether text is converted to UTF-8 or sent as is.

*Result*: Returns True if inserting data to output buffer was successful.


*Properties*

BytesReceived() Long
*Result*: Returns the current size of the incoming data buffer.

LineChange() UniSockLineChange
*Description*: Returns/sets the bytes that determine line change or array separator. This value is used when sending string arrays and when using SendText.

LocalHostname() String
*Description*: Returns the current hostname.

LocalIP() String
*Description*: Returns the current local ip.

LocalPort() Long
*Description*: Returns/sets the current local port.

Mode() UniSockMode
*Description*: Returns/sets the mode of the socket. Binary and text modes are supported. In binary mode DataArrival event is triggered. In text mode TextArrival event is triggered.

Protocol() ProtocolConstants
*Description*: Returns/sets the current protocol. TCP and UDP are supported.

RemoteHost() String
*Description*: Returns/sets the host to connect to, or returns the host that has been connected to.

RemoteHostIP() String
*Description*: Returns the remote host IP address as a string.

RemoteIP() Long
*Description*: Returns the remote host IP address as a 32-bit value.

RemotePort() Long
*Description*: Returns/sets the remote port to connect to, or port that has been connected to.

RequestHost() String
RequestIP() String
RequestPort() Long
*Description*: Information available about the remote host that makes a connection request to a listening socket. Use before accepting a connection to determinte whether you wish to accept the request.

SocketHandle() Long
*Result*: Returns the current open socket handle, or -1.

State() StateConstants
*Result*: Returns the current connection state of the control.

----------


## Merri

I have now fixed a bug that prevented the class from working in Windows Vista. Apparently this is now the only class solution for VB6 that works in Vista.

----------


## c0sm1cSlug

I can confirm the sample code works in Vista!
 I have an unrelated issue, may well be my code as I'm trying to replace my CSocketMaster projects with UniSock.

When my server accepts a connection, the IDE breaks in WndProc() at 

```
' redirect to new location
PostMessageW m_Request(CStr(wParam)), uMsg, wParam, lParam
```

 with "invalid procedure call or argument"

Ive tried resolving it myself as your sample does work and the problem seems to be in Accept() ..  RemoteHost and RemotePort are equal to zero, although it appears the connection has been accepted?

The only difference in my code & the sample code is I'm not passing the RequestID to another control, I only expect a single connection. Any Ideas?

Excellent project though, I'm very gratefull for your work!

----------


## Merri

The problem is that you're still getting old socket's messages, but the old socket is not stored in m_Request array. I'm making some adjustments that should work around this problem (and that will also clean up the memory a bit better than before).

----------


## Merri

The code has been updated.


*Edit!*
It seems the recent fixes have also made the class perfectly stable, I haven't been able to crash it once.

----------


## c0sm1cSlug

yes thats sorted it out! im looking forward to playing around more with this when I have the time, it still seems to crash alot in the IDE tho which is disappointing.

How did you change your code to be vista-compatible? could the same modification perhaps be made to csocketmaster as well?

----------


## Merri

You just have to remove a bit of code that binds a port upon making a TCP connection.

Humm, not Stop button safe anymore... I'll have to take a look into that.

----------


## Merri

Ah, UDP is something I haven't tested, because I had never actually used it myself anywhere. When making the UDP support I simply copied logic from CSocketMaster's code. I guess I just have to find some simple UDP example and then convert it to UniSock and then start debugging the problem. Not today or tomorrow though: I'm not feeling very good, and tomorrow I'll have a busy day.

----------


## jarp0117

Thanks for the reply!

----------


## mut80r

NICE. It works perfectly for my IRC bot (although sometimes I get a GPF, ModName oleaut32, I'm sure it's something I'm doing wrong, bah).

I was just wondering, is it possible to make an array of these or something?

I (stupidly) tried



```
Dim WithEvents Sockets(120) As UniSock

Private Sub Form_Load()
  Dim x As Long
  For x = 0 To 120
    Set Sockets(x) = New UniSock 
  Next
End Sub
```

but WithEvents doesn't like arrays as far as I can tell.

===========================
Thanks in advance.   :Smilie:

----------


## Merri

Make a class module where you use a single instance WithEvents, then you can have multiple copies of that class module as long as that class module does not use events.

To keep the status somewhat updated, TCP should work pretty fine at the moment, UDP is still not fixed. I got a job so I don't have much time at the moment in my hands, and besides work there are other things going on...

----------


## idolpx

I've written an HTTP ActiveX control that uses cSocketMaster and I'm trying to replace it with your UniSock class.  It compiles fine but when I add the resulting ActiveX control to a project it shuts down the IDE.

I'm still trying to pinpoint the problem but was wondering if you had any ideas.

----------


## Merri

I probably have to consider using a different method for handling the messages. Unfortunatenaly the IDE safety tricks go over my area of knowledge (in the full depth level) so I can only go ahead guessing what might be wrong. There may be something else that doesn't work well, one thing that I can think about is the method used for detecting whether the class is running under IDE or not (App.LogMode). Switching to a separately made InIDE function might be worth checking out.

That just as initial thoughts without any testing etc.

----------


## EntityReborn

-misinformed post heh-

----------


## Chris001

I'm looking for a way to limit the upload speed, but apparently that can't be done with the Winsock control. Is it possible with this Winsock replacement?

For example, setting SO_SNDBUF or m_SendBufferSize to a smaller size?

----------


## jarp0117

I am not quite sure about speed because it depends on other factors but the buffer size, you can.

Use setsockopt.....I am changing my receive buffer size for UDP transmissions. Take a look at te code below.

              lngBuffer = 65535  ' MY receive buffer size
              SocketSetOptions m_Socket, SOL_SOCKET, SO_RCVBUF, lngBuffer, 4
              if SocketGetOptions(m_Socket, SOL_SOCKET, SO_RCVBUF, lngBuffer, 4) = SOCKET_ERR then
                  Private_SetState sckerror, "Bind", Err.LastDllError
                  exit function
             else
                 SocketSetOptions m_Socket, SOL_SOCKET, SO_BROADCAST, lngBuffer, 4
                 If SocketGetOptions(m_Socket, SOL_SOCKET, SO_MAX_MSG_SIZE, lngBuffer, 4) <> SOCKET_ERR Then
                    m_ReceiveSize = lngBuffer
                    m_SendSize = lngBuffer
                 End If
.....
.....
.....


The changes were made in the Bind function. Instead of SO_RCVBUF use SO_SNDBUF. The minimum applied by the socket is 8192 bytes and the safest min. you should use is 2048.

Regards,

JARP

----------


## jarp0117

I apoligize but the safest buffer size ONLY APPLIES TO my application. 

Sorry, for the confussion...
Regards,

JARP

----------


## Chris001

Thanks.

I set SO_SNDBUF to 8192, 1024, 512, 32 and 1, but unfortunately it makes no difference to the upload speed.

----------


## jarp0117

What is it you want to do? and why?. Your question was if you could change buffer size using Unisock and the answer is yes. As a matter of fact, this issue is not only Unisock it is in general. The speed, as I said is another issue (There are differences between using UDP and TCP/IP in internal timer implementations).

Regards,
JARP

----------


## Chris001

We're probably getting offtopic, but I'm looking for a way to limit the upload speed, for example to 50kB/s. The reason is that users keep emailing me every single day to implement that feature. There are hundreds or even thousands of applications that allow you to limit the download/upload speed, like peer-2-peer applications, but nobody out there is able to tell me how it's done.

My question was not if I can change the buffer size (I already knew that was possible), but if for example, changing the buffer size (making it smaller) would allow me to upload slower. It seems the answer is No.

----------


## jarp0117

I understand and you are right we probably are off topic so i will give you some quick tips. Check this out http://support.microsoft.com/default...;EN-US;Q233203 and pay careful attention to Qos........I think thats the way to go with some coding effort and then use Unisock for transmission (tcp/ip).

Regards,
JARP

----------


## Chris001

Thanks, jarp0117, I'll look into that.

----------


## jasonce65

This looks very cool, except I can't get it to do anything.  I can see the data coming in on HyperTerminal when set to 'listen' (wait for a call) and I can get data using the regular Winsock control, except that it traps the last 192 bytes of my data and I can't access it until more data comes in.  I'm not running all of these apps at the same time, since my client on the other end is asking for one connection.  Each spurt of data is separated by 3 or 4 minutes, but I need to parse everything I can receive.  Also, it's XML data so there are no CR/LF characters.  Winsock wasn't letting my program receive all of the data.  

I stripped down your sample project to just the server and servernode parts, then I put in Form_Load:

    If Not Server.Bind(5950, "localhost") Then Debug.Print "Server", "Bind failed"
    If Not Server.Listen Then Debug.Print "Server", "Listen failed"
    If Server.Listen Then Label1 = "Listening"


(I added a label1 for messages).  When the program starts, it says "Listening" as expected, but I never get a Server_ConnectionRequest as expected.  I can see the requests for the connection coming in using WireShark.

Also, occasionally, when I change a bit of code in Form UniSocketDemo, and then click away from the VB6 IDE, say to an Internet Explorer, the whole IDE crashes.

Any ideas on what I can try.  I only need to receive data.

----------


## Merri

There is at least one oddness, calling Listen two times:

```
If Server.Bind(5950, "localhost") Then
    If Server.Listen Then
        Label1.Caption = "Listening"
    Else
        Label1.Caption = "Listen failed"
    End If
Else
    Label1.Caption = "Bind failed"
End If
```

If you are displaying a message box it will prevent the events from being processed (under IDE).

----------


## Merri

Just to let everyone know, I am now working on a fixed version that will use the same subclassing machine code as CSocketMaster. However, just like this far, I'm rewriting the VB6 code entirely to clean up any clutter.


Doing this as I now need UniSock's special features but I don't want to modify CSocketMaster.

----------


## Merri

Some updates to let you know something is happening: I've been doing very careful work on analysing how things work and I've kept reading the initialization code over and over again to ensure there are no errors and that the logic _should_ be correct. I've done some things very differently than they're done in CSocketMaster though... for one, I'm still creating a custom window class instead of using a STATIC. At the moment I'm also starting the subclass code immediately upon window creation, which is unlike in CSocketMaster: will see if this can be done or not. If I can't do it like that, well, that is a problem of that time.

I don't like how CSocketMaster separates all the small code portions into a multitude of functions, I've been able to keep things far simpler. I now have one longer code block that reveals all the logic required for initializing everything. This is also true for the reverse, things are cleaned up in a clear order in one place.

Once all this hard work is complete I can mostly paste all the old UniSock code in place and finally start debugging for any issues.

----------


## EntityReborn

Nice work Merri! I've moved to .Net (Sockets are way better, and there is a winsock lookalike using sockets), but when I do vb6 projects (nostalgia rules), I will def. use this!

----------


## Merri

Some progress reports. I have now rewritten the subclasser to fit UniSock. The good news is that the class does not crash IDE even when pausing or stopping IDE and thus the machine code is working as it should. The bad news is that there is some bug somewhere that corrupts a few values that I read from memory and I'm not going to figure it out in the next few hours, leaving that for tomor... err... later. The class is still fully unusable at the moment.

----------


## c0sm1cSlug

Its great to know UniSock is progressing Merri, Keep up the good work!
Any chance of an update?  :big yellow:

----------


## dee-u

The last time I've checked your's doesn't support UDP, what about integrating it?  :Smilie:

----------


## Merri

Yup, this can be read about in earlier posts; to continue with this project I'd need many hours of continuous spare time which I haven't had in a good while.

----------


## ingvar17

i found solution for UDP

----------


## ingvar17

to use UDP 

declare in form header:
Private WithEvents Client As UniSock' ---it already shoud be there

in Form_Load event:

Private Sub Form_Load()
    Set Client = New UniSock
    Client.Protocol = sckUDPProtocol

    Client.Connect 0, 3040' to connect remote broadcast address 255.255.255.255 and use port 3040(netfinder)

in UniSock.cls needs change:
1)in Connect event after 

                        SocketSetOptions m_Socket, SOL_SOCKET, SO_BROADCAST, lngBuffer, 4
                        '-----------------------------
                        m_RemoteHost = -1'--add this line to use broadcast address 
2)in Private_Bind after:
                    m_LocalPortBind = lngLocalPort
                    '-------------------------------
                    Private_SetState sckOpen'----add this line to proceed
3)in Private_Message uncomment after:
                    If lngRemoteIP = INADDR_NONE Then
                        ' resolve IP of hostname
                        '------------------------------
'                        lngResult = SocketGetHostByName(m_RemoteHost)
'                        If lngResult Then
'                            ' get the resolved IP
'                            RtlMoveMemory udtHostent, ByVal m_HostentPointer, Len(udtHostent)
'                            GetMem4 udtHostent.hAddrList, lngIPPtr
'                            GetMem4 lngIPPtr, lngRemoteIP
'                        Else
'                            Private_SetState sckError, "Private_Message", WSAGetLastError
'                        End If
                    End If
'cose udp not need to resolve remoteIP-- much quicker this way

4) i dont now why in my case XP_pro i get error message to 

GetData = (SocketReceiveFrom--- i changed it to

GetData = (SocketReceive(m_Socket, bytArray(0), MaxLen, lngFlags) <> SOCKET_ERR)

as in TCP -get_data-- in my 'Case vbByte' procedure in 'get_data' rutine
5) to read out data in form 'Private Sub Client_DataArrival(ByVal BytesTotal As Long)':
i used this way to read out data:
    Dim byteData() As Byte

    Client.GetData byteData, vbByte, 4096
Debug.Print StrConv(byteData, vbUnicode)

that's it

I Hope this comment helps anybody to use this class with UDP 
great job enyway- i waited this kind of class for a long time and find this a very useful in vb6

----------


## Inuya5ha

I'm having a small problem with the Unisock, because for some reaon it only transfers the first 8 KB of each file or page I send, and disconnects itself without sending the entire files.

Here's the current debug for a file request and send process, notice I use spServer to listen to requests and usServidor to send the data back:

>>> spServer_ConnectionRequest (Set usServidor = New UniSock; usServidor.Accept RequestID)
>>> usServidor_StatusChange: 7 (Connected)
>>> usServidor_Connect
>>> GET /files/myfile.png
>>> usServidor_SendProgress BytesSent=8192 BytesRemaining=125638
>>> usServidor_StatusChange: 8 (Closing)
>>> usServidor_StatusChange: 0 (Closed)

This issue is driving me mad, only contents smaller than 8 KB are entrirely transferred, bigger files never arrive completely to the client side.   :Frown: 


Also, how do I create an array of Unisocks so I can *attend multiple requests at once?* If someone can clarify Merri's explanation when he said...




> Make a class module where you use a single instance WithEvents, then you can have multiple copies of that class module as long as that class module does not use events.


.. I will appreciate it.  Exactly how do I create "multiple copies of that class module" *dinamically at run time?* I don't know how many requests may arrive at the same time, so I can predict how many sockets will I need simultaneously. Thanks in advance

----------


## ingvar17

coud you post me code you running
propably you sendsocket with closesocket command
i running UniSock_2008-08-14.zip and all seems OK
'--------
ofcouse 'RaiseEvent SendProgress' event is different of winsock events
just replace 
'RaiseEvent SendProgress(lngPos, m_SendBufferSize)'
with
'RaiseEvent SendProgress(m_SendSize, m_SendBufferSize - lngPos)'
and
'RaiseEvent SendProgress(m_SendBufferSize, 0)'
with
'RaiseEvent SendProgress(m_SendBufferSize - lngPos, 0)'
'-----------
seems that vesa is automatically reads sended bytes and reports instead of bytessent=totalsend, bytesremaining=totalBytesToSend

ingvar

----------


## Merri

The subclassing thunk used in this project is, unfortunatenaly, not fit for Winsock use. This causes problems especially when multiple classes are used. The thunk should be replaced with the one from CSocketMaster and other code changes should be done accordingly, but I haven't had the interest (vs. time) to do this.

As the class is now it is, at times, unstable as the thunk does not always properly deal with unloading a socket.

----------


## ingvar17

to Inuya5ha 


also i forget - seems that you need compile to P-Code

----------


## Merri

Due to "lately" getting a lot of interest in this project I'm now doing some research on getting the class working properly. The hard part is that as I have to use CSocketMaster's ASM thunk (because it is known to work even if the VB code is awful at parts) I'm a bit challenged in converting that code to a class only use. CSocketMaster uses a module and a class together.

To make my life easier I've been gathering up some documentation to work with:

```
CSocketMaster's ASM thunk

XX |	00010203	04050607	08090A0B	0C0D0E0F
---|	--------	--------	--------	--------
00 |	58505055	89E55753	515231C0	EB0EE8xx	0F EbMode
10 |	xxx01x83	F8027422	85C07425	8B45103D
20 |	00080000	74433D01	08000074	5BE82000
30 |	00005A59	5B5FC9C2	1400E813	000000EB
40 |	F168xxxx	x02x6AFC	FF750CE8	xxxxx03x	42 Previous WndProc 	4C SetWindowLong
50 |	EBE0FF75	18FF7514	FF7510FF	750C68xx	5F Previous WndProc
60 |	xxx04xE8	xxxxx05x	C3BBxxxx	x06x8B45	64 CallWindowProc	6A MsgCountA
70 |	14BFxxxx	x07x89D9	F2AF75B6	29CB4B8B	72 MsgTableA1
80 |	1C9Dxxxx	x08xEB1D	BBxxxxx0	9x8B4514	82 MsgTableA2	89 MsgCountB
90 |	BFxxxxx0	Ax89D9F2	AF759729	CB4B8B1C	91 MsgTableB1
A0 |	9Dxxxxx0	Bx895D08	8B1B8B5B	1C89D85A	A1 MsgTableB2
B0 |	595B5FC9	FFE0

= 182 bytes

 #	Decimal position
00	12	JMP [EB0E] -> NOP NOP [9090] (to enable IDE breakpoint check within IDE)
01	15	EbMode
02	66	Previous WndProc
03	76	SetWindowLongA
04	95	Previous WndProc
05	100	CallWindowProc
06	106	MsgCountA
07	114	MsgTableA1 (Asynchronous handle)
08	130	MsgTableA2 (Object pointer = class)
09	137	MsgCountB
10	145	MsgTableB1 (Socket handle)
11	161	MsgTableB2 (Object pointer = class)


CSocketMaster initialization:
1) InitiateProcesses (increase socket counter, in module)
2) Once: Subclass_Initialize (ASM thunk, in module)
3) Once: InitiateService (Winsock, in module)


1) CSocketMaster creates a message window when connecting the first time.
2) There is only one message window for all sockets.

CSocketMaster termination:
1) CleanResolutionSystem (in class)
2) DestroySocket (in class)
3) FinalizeProcesses (decrease socket counter, in module)
4) Once: Subclass_Terminate (end subclass, free memory, in module)
5) Once: Subclass_UnSubclass (restore original WndProc)

' ASM thunk from string to Currency array
Option Explicit

Private Declare Sub RtlMoveMemory Lib "ntdll" (Destination As Long, Source As Long, ByVal Length As Long)

Private Sub Form_Load()
    Dim strHex As String, strASM As String * 92
    Dim curData(20) As Currency
    Dim lngA As Long
    strHex = "5850505589E55753515231C0EB0EE8xxxxxxxx83F802742285C074258B45103D0008000074433D01080000745BE8200000005A595B5FC9C21400E813000000EBF168xxxxxxxx6AFCFF750CE8xxxxxxxxEBE0FF7518FF7514FF7510FF750C68xxxxxxxxE8xxxxxxxxC3BBxxxxxxxx8B4514BFxxxxxxxx89D9F2AF75B629CB4B8B1C9DxxxxxxxxEB1DBBxxxxxxxx8B4514BFxxxxxxxx89D9F2AF759729CB4B8B1C9Dxxxxxxxx895D088B1B8B5B1C89D85A595B5FC9FFE0"
    For lngA = 1 To 182
        MidB$(strASM, lngA, 1) = ChrB$(Val("&H" & Mid$(strHex, lngA * 2 - 1, 2)))
    Next lngA
    RtlMoveMemory ByVal VarPtr(curData(0)), ByVal StrPtr(strASM), 182
    For lngA = 0 To 20
        Debug.Print "curASM(" & lngA & ") = " & Format$(curData(lngA), "0\.0000\@")
    Next
End Sub

' resulting array
curASM(0) = 60055210061.2645@
curASM(1) = 653186003.0143@
curASM(2) = 24826125609.6095@
curASM(3) = 44000932998.7215@
curASM(4) = 893017331.1255@
curASM(5) = 92626787.4057@
curASM(6) = -44108895140.8696@
curASM(7) = -15132094744.6252@
curASM(8) = -2583940286.2036@
curASM(9) = 38.9313@
curASM(10) = 14743649335.5771@
curASM(11) = 292870985.0788@
curASM(12) = 38.9231@
curASM(13) = 50110990103.7986@
curASM(14) = -27716840956.6978@
curASM(15) = -84094044991.6901@
curASM(16) = 21558168466.2695@
curASM(17) = 14607264862.6786@
curASM(18) = -9475756134.9177@
curASM(19) = 20568209907.7300@
curASM(20) = 6027885582.3052@
```


*Update!*
I've done some good progress, but still far away from anything releasable. A lot of to be done is just adjusting old UniSock code to the new code based on CSocketMaster's ASM thunk, but there are also some bigger changes to be done (such as fixing Accept).

----------


## Badboyjt432

Couple questions, I don't know if they have been answered. Can this be used over WAN? Also does the bind command set the remote host, a local host, or just a host in general? I wrote a winsock app, and i'm trying to convert all of it to unisock so I can take it with me. It's a chat program among other things.

Do the server/client have to be in the same project? Also what is servernode for?

----------


## Zach_VB6

Hey Merri, could you help me out?

Here's what I'm trying: http://www.pastie.org/private/qztzszs9mh7qvxsiwidmw
Here's the output: http://www.pastie.org/private/k6ieb5in0j1uhgoc6tftia

----------


## Merri

Use the Connect event. Do not wait in a loop. Also, any continuous DoEvents is likely to break events, ie. by using DoEvents you may actually block the Winsock messages to the UniSock class.


The current UniSock version is still a bit broken; I don't know when I have the fixed, hopefully 100&#37; stable version out, so many things going on in my life atm.

----------


## Zach_VB6

I am trying to make a function like the following:



```
Public Function Request(ByRef Output As String, ReqType As String, URL As String, Optional Referer As String = vbNullString) As Boolean
```

and call it like:

```
Dim HTML As String
Request HTML, "GET", "http://www.google.com/"
MsgBox HTML, , "Google's HTML"
```

And I figured the best way to write that function is with a loop.

----------


## Merri

You have to make things event based. So this is how things should work:Request function is called. This returns True if success on starting a connection attempt. Request string is stored so that it can be accessed from any local function.Upon connection Connect event fires. The request string is sent.DataArrival event fires. It may fire multiple times for a single request, thus buffering is required. Data moves over the Internet in packets that are limited in size, this is why data may be split in multiple responses.Once all data is received, you may call a custom procedure to bring up the message box. You can also close the connection.Error event is likely to cancel the request.

If you want to simplify things and you only need to download files, you can also check out UserControl's asynchronous download features. However, you still have to deal with events. Events are how VB6 works.

----------


## Zach_VB6

I *know* that the looping method will work with Winsock. (See attachment here: http://www.vbforums.com/attachment.p...1&d=1199419733)

And I can't use a API or anything else to simply download the files... I need to store the cookies and such. It also needs to be as fast as possible, hence why I'm using Winsock (slow to write & open a file)

----------


## Merri

I have to recommend staying with the Winsock control. As far as I know DoEvents causes problems with anything in VB6 where VB code processes Windows window messages, thus you can't get that done with UniSock the way you want. For example if you add DoEvents to code executed by UniSock you'll get an instant crash (if I recall correctly).

----------


## Zach_VB6

Same thing will happen with cSocketMaster I assume?

----------


## Merri

UniSock's current version uses SelfCallback ASM thunk and creates a custom message window, which means all window messages are sent directly to VB6 code.

CSocketMaster instead creates a STATIC window for messages and then subclasses this with a bit more specialized ASM thunk. I haven't tested whether this makes a difference with DoEvents; but I know the current UniSock implementation is more vulnerable to problems. This is why I've been converting CSocketMaster's ASM thunk for UniSock, but I still have a lot of work to do to get it all fully working. At the moment the code is able to create a single message window for all UniSock classes and subclass it for each and that part is stable, but all the other code is not adjusted yet.


If you try CSocketMaster you should have a look at Vista issue and make sure you have a Vista/Windows 7 compatible version of it. There is also criticism to CSocketMaster over the forums/web which you may wish to search for to know what issues it has.

----------


## Zach_VB6

CSocketMaster worked fine for me. Thanks though. I'll keep UniSock saved  :Big Grin:

----------


## chunk

Hi All,
I know this very old thread but still have a question  :Frown: 
Can i send the Unicode Data the the server?
Im using the UniText control written by marry.


```
Private Sub WS_Connect()
  MsgBox "Unisock Connected " & WS.State
Dim Url As String
Dim StrTh As String

StrTh = "GET " & "http://localhost/page.php?name=" & Text1.Text & "&email=" & Text2.Text & "&msg=" & UniText1.Text & vbCrLf
MsgBox StrTh
StrTh = StrTh & "HTTP/1.0" & vbCrLf
StrTh = StrTh & "Accept: */*" & vbCrLf
StrTh = StrTh & "Accept: text/html" & vbCrLf & vbCrLf
StrTh = StrTh & "Content-Type: application/x-www-form-urlencoded" & vbCrLf
 
WS.SendData StrTh
 
MsgBox WS.State
End Sub
```

----------

