FreeBASIC Winsock TCP Chat Program

User projects written in or related to FreeBASIC.
cenozoite
Posts: 243
Joined: Aug 21, 2005 21:41

Post by cenozoite »

Chronos, I have no objection to your posting your program as a new project, even if it's based on my source. Especially since this thread is already kind of long, and who wants to have to read through a dozen messages before getting to a new message full of code. Start it off fresh in its own thread if you like. I plan to eventually expand mine to do multi-user chat and a few other things, and I'll probably put that in a new thread as well so as not to confuse beginners who just want to see the basic tutorial first.

A couple of other quick notes about my program. I've modified it at home so that it now works correctly under both 0.14b and 0.15b, but I'm not bothering to post those changes here since I know that once the next release of 0.15 comes out shortly, the View Print command will have been messed around with further and I'll just have to redo things again. For now I'll just leave the disclaimer that it works under 0.14, and change it permanently once the stable edition of 0.15 is released.

As for the simultaneous incoming and outgoing messages, there is actually a far simpler method of doing that than the threaded/trafficlight system I'm using. It's just not been implemented yet due to some bugs in the current FB version which should be worked out by the next release.

The method, briefly, is just to put the incoming message checking routine (with a selectsocket command to avoid blocking) in the same DO-LOOP with the Brint$ outgoing message routine, and let the loop run them together repeatedly. Something like (really generalizing here, code not executable):

Code: Select all

DO

If SelectSocket (3,@fdset, null, null @tv) >0 then
Use RECV to receive message and print it on the screen etc...
End if

Sleep 200

If Inkey$<>"" then
Use the Brint$ code to print whatever key was pressed, or backspace, etc.
End if

LOOP
That's just a general outline for checking for incoming and ougoing text using just one loop for both purposes, without all that threaded trafficlight jazz. There are just two problems in the current release:

1. Currently Inkey$ only ever stores one key in the buffer, and clears the entire buffer when it's called, instead of just removing that one key from the buffer. So if the user somehow manages two or more very quick keypresses before the program gets to that section, it will only read one, and the rest will just be lost. This bug is reportedly already fixed in the next release.

2. Note the use of Sleep 200 in between the two sections. I put that there because using Selectsocket over and over and over again at the computer's maximum speed, with no pauses, tends to drive CPU usage up to near 100%. Having it pause for just a brief moment in between drops that way down, to acceptable levels. The problem is that SLEEP clears the inkey buffer as well, resulting in the same problem as #1 above. That apparently won't be changed in the next release.

However, one can of course always just substitute somthing like

T=timer
While timer<T+0.2
Wend

So that bug really isn't much of a problem, it's just slightly cumbersome to get around. Thus once the inkey$ thing is fixed, the simultaneous thing should be even easier.
Chronos
Posts: 40
Joined: May 31, 2005 15:21
Location: KY, USA
Contact:

Post by Chronos »

OK, I'll start up a new thread so as to not clutter up this one with additional code snippets. I'll remove the previously-posted code, since I'd only be providing unnecessary redundancy. I do humbly request the use of the multi-user version too, if you feel so inclined to allow it. Of course, feel free to use any modifications I have made (and will make) to the source.

Keep up the excellent work!
cenozoite
Posts: 243
Joined: Aug 21, 2005 21:41

Post by cenozoite »

Alrighty, a bit of an update. With the early release of an interim, unofficial, under-development compiled CVS version of FB 0.15b, courtesy of the devs in response to a request, I've gone ahead and revamped my chat program to take advantage of the compiler improvements. The absence of previous bugs has allowed me to make this version considerably simpler, which should benefit the beginner, so I'll paste the new program code in below for reference.

Notes:

1. This program ONLY works with the special interim CVS version of FB 0.15b (or later), which can be found here:

FB015b-20050915-Win32-Setup.exe

My program appears to run fine under this CVS version, but keep in mind that it's not official so there are no guarantees about anything else. When the stable version is released, I'll edit this post to reflect it.

2. I've done away with the threaded trafficlight system from the previous version, in the original post. That system was created for FB 0.14, which had a bug in the Inkey$ function, but now that that's fixed in the CVS version, I've implemented a much simpler single-loop routine for handling both incoming and outgoing messages, as mentioned previously a couple of messages ago. The original program code will be left intact in the first post, for anyone who wants to use it with FB 0.14.

3. Multi-user version is in the works and will be released in its own topic, at a future time.

Here's the code:

Code: Select all

'This is an example of a small, direct client-to-client two-way
'simultaneous chat program using Winsock TCP in FreeBASIC. The 
'important segments are the ones illustrating the syntax for opening
'socket sand establishing connections either as the connection
'initiator (client) or connection acceptor (server). The specific
'subsequent methods for sending and receiving data are more flexible,
'and the ones presented here have been chosen for simplicity rather
'than efficiency.

'The basic steps to follow for each choice (client or server) are:
'Client                         Server
'1. Open socket                 1. Open socket
'2. Define socket details       2. Define socket details
'3. Connect socket              3. Bind socket to socket details
'                               4. Listen on socket
'                               5. Accept connection on socket
'
'Once each side has completed its steps successfully and the 
'connection is established, they are ready to Send and Receive
'data back and forth, both ways. The steps above are highlighted
'in code below where they occur.


'Preliminary declarations and definitions

#include "win\winsock.bi"     'Header to include for Winsock function
option Escape
Width 80,25
Locate ,,0

Declare Sub GetMyIp
Declare Sub Generr
Common shared s as socket, r as socket, q as socket
Common Shared sa as sockaddr_in, sb as sockaddr_in, sc As sockaddr_in, sd as sockaddr_in
Common Shared inmessage As zString*316, outmessage As zString *316
Common Shared myname$,remotename$,c,p,textline,chatfinished
Common Shared fdset As fd_set, tv As timeval
Common Shared hostname as string * 256, hostentry as HOSTENT ptr
Common Shared pinaddr as pin_addr, localip as zstring ptr, ipparser as ubyte ptr
Const NEWLINE = "\r\n"
Dim wsad as WSAData
Dim addy as String
Dim inip As Integer
inip=sizeof(sc)
tv.tv_Sec = 0: tv.tv_Usec = 1000
myname$="User"


MenuStart:
'WSAStartup must first be called to intitalize Winsock
'Tries Winsock version 1 if version 2 isn't found

if (WSAStartup(&h202, @wsad))=-1 then
      if (WSAStartup(&h101, @wsad))=-1 then generr
end if

chatfinished=0

'Main menu. Lets user change his display name, and most importantly
'select either Client or Server mode, for estabslishing a connection
Cls
Color 15,1
Print space$(79)
locate 1,1
Print "Client-Server Chat Test Program, by Cenozoite"
Color 7,0
Locate 2,1
Print space$(79)
Print "Enter choice below:"
Print String$(50,Chr$(196))
Print"(1) Client Mode (Initiate remote connection)"
Print"(2) Server Mode (Wait for remote connection)"
Print"(3) Set name (Currently set to ";
Color 15:Print myname$;
Color 7:Print")"
PRINT"(4) Exit"


Makeachoice:
Sleep 
choice$=inkey$:choice=Val(choice$)
if choice$=chr$(27) then choice=4
If choice<1 Or choice>4 Then GoTo Makeachoice

If choice=4 Then 
wsacleanup    'This shuts down Winsock if the user quits
End 1
end if

If choice=3 Then
For x=3 To 8
Locate x,1
Print Space$(79)
Next x
Locate 3,1
Print "Enter new display name (or hit Enter to leave as ";
Color 15:Print myname$;
Color 7:Print"): ";
Input "",mn$
If Trim$(mn$)<>"" Then myname$=Left$(Trim$(mn$),12)
For x=3 To 8
Locate x,1
Print Space$(79)
Next x

GoTo MenuStart
End If


If choice=1 Then    'User specifies a remote IP to connect to here
For x=3 To 8
Locate x,1
Print Space$(79)
Next x
Locate 3,1
Input "Enter remote dot-format IP ADDRESS to connect: ",addy
addy=Trim$(addy)
If addy="" Then GoTo MenuStart
mode=1
End If


If choice=2 Then
For x=3 To 8
Locate x,1
Print Space$(79)
Next x
Locate 2,1
mode=2
End If

'***** STEP 1 for both CLIENT and SERVER modes: Open the socket
'This socket will be opened the same way for either mode, so
'it's done up front as follows.
s = opensocket( AF_INET, SOCK_STREAM, IPPROTO_TCP )
if s <= 0  Then generr  'If there's an error, quit
'******


If mode=2 then  'If the user selected SERVER MODE
Call GetMyIp    'This is a helpful but totally optional Sub
Print "Awaiting remote connection... hit ESCAPE to cancel..."
color 7,0    
    
'***** STEP 2 for SERVER MODE: Define the socket details
    sa.sin_port			= htons( 8501 )
	sa.sin_family		= AF_INET
	sa.sin_addr.S_addr	= inaddr_any
'*********

'*** STEP 3 for SERVER MODE: Bind the socket to the socket details
nbit = bind( s, @sa, len(sa))
if nbit=socket_error Then closesocket(s):generr
'*********

'**** STEP 4 for SERVER MODE: Listen on the socket
nlis= listen( s, somaxconn) 
if nlis = SOCKET_ERROR  Then closesocket( s ):generr
        

''** This could be called step 4a. It's not needed, but stops the 
'socket from blocking while it's waiting to accept, and gives the user
'the option of aborting by hitting Escape
do
if inkey$=chr$(27) then esclause=1:exit do
FD_ZERO (@fdset)
FD_SET_ (s,@fdset)

nRet = selectsocket( 3, @fdset, NULL, NULL, @tv )
if nret>0 then exit do
loop
if esclause=1 then esclause=0:closesocket (s):goto MenuStart
'****************

'**STEP 5 for SERVER MODE: Accept incoming connection on the socket
r = accept( s, null, null )    		  		 
If 	r = socket_error Then closesocket(r):closesocket(s):generr
swap s,r
Close(r)
'*******

'SERVER MODE now completed. Two-way connection established and ready.
GoTo beginchat
End If ' for If mode=2, way way up the screen


If mode=1 then   'If the user selected CLIENT MODE

'******* STEP 2 for CLIENT MODE: Define the socket details
    sa.sin_port			= htons( 8501 )
	sa.sin_family		= AF_INET
	sa.sin_addr.S_addr	= inet_addr(addy)
'*********************

color 15,0	
Print ""
Print "Connecting... hit ESCAPE to cancel...";
try=1

do
'****STEP 3 for CLIENT MODE: Connect the socket to the remote host
ncon = Connect( s, @sa, Len( sa ) )
If ncon<>socket_error then exit Do
'*****************
if inkey$=chr$(27) then try=31
try=try+1
if try>30 then exit do
Loop
  
if try>30 then 
closesocket(s)
Print "Failed to connect. Hit any key to return."
sleep
goto MenuStart
end if
color 7,0


' CLIENT MODE now completed. Two-way connection established and ready.
GoTo beginchat

End If 'for If Mode = 1, up the screen
  

Beginchat:

If (myname$="User" or myname$="ServerUser") And mode=1 Then myname$="ClientUser"
If (myname$="User" or myname$="ClientUser") And mode=2 Then myname$="ServerUser"

'Tell the remote machine my display name and get its display name
outmessage=myname$
bsent=send (s, @outmessage,316,0)
if bsent=-1 then closesocket(s):generr

brec=recv(s,@inmessage,316,0)
If brec <=0 Then closesocket(s):generr
remotename$=Trim$(inmessage)

'Get remote IP Address
gpn=getpeername(s,@sc,@inip)
If gpn<>-1 then
ipparser=@sc.sin_addr.s_addr
remoteip$=str(ipparser[0])+"."+str(ipparser[1])+"."+str(ipparser[2])+"."+str(ipparser[3])
End if

'Set up the chat screen
Cls
Locate 1,1
Color 15,2:Print space$(79):locate 1,1
Print "Now chatting with "+remotename$+" ("+remoteip$+")"
Color 2,0
Print String$(79,Chr$(196))
Color 7,0
Locate 20,1:Print String$(79,Chr$(196))
Locate 21,1
Color 0,7:Print Space$(79)
Locate 21,1
Print "Type message below and hit ENTER to send. Hit ESCAPE to end chat."
Color 7,0


'This is where the chat begins, and incoming and outgoing messages
'are processed. It's a two-part infinite loop that runs continuously,
'with Part 1 checking for, receiving, and printing incoming messages,
'and  Part 2 checking for, printing, and sending outgoing messages,
'over, and over, and over again.

Normalstate:
textline=4
c=22:p=1

Do

'Part 1 of 2, Incoming Message Check
FD_ZERO(@fdset)
FD_SET_ (s,@fdset)
if (selectsocket( 3, @fdset, NULL, NULL, @tv ))>0 then
'Basic syntax for RECV command
brec=recv(s,@inmessage,316,0)
If brec<1 Then chatfinished=2:exit do

View Print 3 To 18

If textline>18 Then
Locate 18,1:Print ""
textline=18
End If

locate textline,1
Color 9,0
Print remotename$;": ";
Color 15,0
Print Trim$(inmessage)
Color 7,0
textline=CsrLin+1
View Print 1 To 25

End If ' The SelectSocket Check


'Part 2 of 2, Outgoing Text/Message Check

k$=Inkey$
If k$<>"" then
locate c,p

'If User types a valid alphanumeric key
If k$<>Chr$(8) And k$<>chr$(13) and k$<>chr$(27) and InStr(k$,Chr$(255))=0 Then
Locate c,p
Print k$; 
tempmessage$=tempmessage$+k$
End If

'If User hits backspace
if k$=chr$(8) Then
if pos=1 and csrlin<>22 then locate csrlin-1,80 
Locate CsrLin, Pos-1:Print " ";
locate csrlin, pos-1
tempmessage$=Left$(tempmessage$,Len(tempmessage$)-1)
end If 

if (len(tempmessage$)=79 or len(tempmessage$)=158 or len(tempmessage$)=237) and k$<>chr$(8) then locate (csrlin+1),1
if len(tempmessage$)=315 then k$=chr$(13) 'Force end of message
c=CsrLin:p=pos

'If User hits escape
if k$=chr$(27) then chatfinished=1:exit do

'If User hits Enter (print and send the message)
If k$=Chr$(13) and trim$(tempmessage$)<>"" Then
outmessage=tempmessage$
tempmessage$=""
c=22:p=1

View Print 3 To 18

If textline>18 Then
Locate 18,1:Print ""
textline=18
End If

locate textline,1
Color 10,0
?myname$;": ";
color 14,0
?trim$(outmessage)
Color 7,0
textline=CsrLin+1
View Print 1 To 25
Locate 22,1:Print Space$(79);
Locate 23,1:Print Space$(79);
Locate 24,1:Print Space$(79);
Locate 25,1:Print Space$(79);

'Basic syntax for SEND command
bsent=send (s, @outmessage,316,0)
if bsent=-1 then closesocket(s):generr
End If 'for If User hits Enter

End If  'For User hits a key

Loop
'End of main chat section



'Section handles chat termination by either side
chatover:
closesocket(s)
View Print 3 To 18

If textline>18 Then
Locate 18,1:Print ""
textline=18
End If

locate textline,1
color 12
if chatfinished=1 then ?"Chat terminated. Hit ESCAPE to end session."
if chatfinished=2 then ?"Chat terminated by other side. Hit ESCAPE to end session."
while inkey$<>chr$(27):wend
chatfinished=0
view print 1 to 25
closesocket(s)
wsacleanup
goto MenuStart



Sub GetMyIP
'***This subroutine attempts to determine user's IP Address
'automatically, using two methods. First uses the direct Gethostname
'method, and as a backup, checks a website to get the public IP if
'it's different from local. Entirely optional.

locate 3,1
color 15,0
Print"Entering SERVER Mode..."
Print""
Print"Attempting to determine local IP address, one moment please..."
Print""
color 7,0

ghn=GetHostName(@hostname, 256)
hostentry = gethostbyname( hostname )

'Standard Winsock method of getting IP Address from hostentry:
pinaddr=hostentry->h_addr
localip=inet_ntoa(*pinaddr)
myip$=*localip

'Alternate method of getting IP Address from hostentry. To use this
'method, comment the above three active code lines, and uncomment
'the two here below:
'ipparser=hostentry->h_addr
'myip$=str(ipparser[0])+"."+str(ipparser[1])+"."+str(ipparser[2])+"."+str(ipparser[3])


q = opensocket( AF_INET, SOCK_STREAM, IPPROTO_TCP )

    sd.sin_port			= htons( 80 )
	sd.sin_family		= AF_INET
	sd.sin_addr.S_addr  = inet_addr("63.208.196.105")

if ( connect( q, @sd, len( sd )) = SOCKET_ERROR ) then closesocket( q )
outmessage = "GET /" + " HTTP/1.0" + NEWLINE + "Host: " +  NEWLINE +"Connection: close" + NEWLINE + "User-Agent: GetHTTP 0.0" + NEWLINE + NEWLINE
if ( send( q, @outmessage , len(outmessage), 0 )) = SOCKET_ERROR  then closesocket( q )
	
do 
bytes = recv( q, @inmessage , 316, 0 )
if( bytes <= 0 ) then exit do
wholemessage$=wholemessage$+inmessage
loop

closesocket(q)
beg=instr(wholemessage$,"Address: ")
en=instr(wholemessage$,"</body>")
altip$=mid$(wholemessage$,beg+9,(en-1)-(beg+8))
if val(altip$)>0 and (val(altip$)-int(val(altip$)))>0 and altip$<>myip$ then myip$=altip$

color 15,0
if val(myip$)>0 then
print "Your Local IP Address Is: ";
color 10,0:Print trim(myip$):color 15,0:Print ""
Print "Remote party should enter that address after selecting ";
color 10,0:Print "Client Mode.":color 15,0:Print ""    

else
color 15,0
Print "Your Local IP Address could not be determined automatically. Please use an"
Print "appropriate Internet Web Site or other service to determine your Local IP."
Print ""

end if
End Sub



'Error section
Sub Generr
cls
Locate 10,0
color 15,0
?"There was a General Error of a General Nature, and the program"
?"could not continue. Because this is only a test program, specific"
?"error trapping has not been implemented. However for your interest,"
?"Winsock said:"
?""
?"Error code ";WSAGetLastError
?""
closesocket(s)
wsacleanup
?"Hit any key to exit the program..."
color 7,0
Sleep
end
end sub
Last edited by cenozoite on Sep 19, 2005 18:17, edited 2 times in total.
Ryan
Posts: 695
Joined: Jun 10, 2005 2:13
Location: Louisville, KY
Contact:

Post by Ryan »

Hey, can't remember if I've commented on your code yet or not. Basically, I appreciate it. It's what I wanted to do back when I figured out how to use Winsock myself. = P I had to trudge through C examples, the Winsock.hlp file, and some other API stuff while I figured out Asynchronous sockets (only to arrive at a threaded approach anyways). Basically, I was wondering about your local IP function. I use the following code:

Code: Select all

'*******************************************************************************
'* GetLocalIP () as string
'* - Returns the host IP in string form for display purposes
function GetLocalIP () as string
  
  dim nameBuf as string * 256, lRet as long, hostEntPtr as LPHOSTENT
  dim pinAddr as PIN_ADDR, localipptr as byte ptr
  
  getlocalip = "127.0.0.1"
  
  'Puts the host name into nameBuf
  lRet = gethostname(@nameBuf, len(nameBuf))
  
  'Directs our host entity pointer to the entity for the host's name
  hostEntPtr = gethostbyname(nameBuf)
  
  'Grabs the first address from the address list of the host entity
  pinAddr = hostEntPtr->h_addr
  
  'Formats the value to what we see as an IP address!
  localipptr = inet_ntoa(*pinAddr)
  
  getlocalip = *localipptr

end function
But it returns your network address if you're on a network, so it always shows up as 192.168.0.2. So, I had 2 questions. 1) What is that web page you linked to? If it's some quickie thing you've generated that may not always be up, I won't bother. But if it's something stable and long lasting, I was wondering if I might use that in my server code for my Rogue entry at FBTK. 2) I was wondering why you used gethostname without a return value like I did. I just did it b/c that's what the code in the .hlp looked like. It works either way, I just didn't know why you left it out. (And I guess a third question... do you know anything about the pointer warnings your program gets at compile? They show up in mine as well, like with GetHostName using a string it says we're passing a different pointer type. Any clues?)
cenozoite
Posts: 243
Joined: Aug 21, 2005 21:41

Post by cenozoite »

Thanks for your appreciation and interest, Ryan. I had to trudge and struggle through the learning process myself, so I'm more than happy if I can make it a little easier for anyone else. I'll try to address your questions/points sequentially below:
Ryan wrote: 1) What is that web page you linked to? If it's some quickie thing you've generated that may not always be up, I won't bother. But if it's something stable and long lasting, I was wondering if I might use that in my server code for my Rogue entry at FBTK.
http://checkip.dyndns.org/ (63.208.196.105)

It's one of quite a few apparently stable websites that seem to exist for the express purpose of telling a user his public IP Address. There are a bunch that work, but this one had the cleanest, smallest amount of text and thus was the easiest to deal with. Other more elaborate ones include:
http://www.showmyip.com
http://whatismyip.com

I implemented that backup check precisely for users who are on a network or behind a NAT and can't get their public IP the easy way.
Ryan wrote: 2)I was wondering why you used gethostname without a return value like I did. I just did it b/c that's what the code in the .hlp looked like. It works either way, I just didn't know why you left it out.
Basically my lazy assumption that Gethostname isn't a call that's likely to fail, and the recognition that the return value is only ever used for error checking anyway. I've used the error-checking return value for most other winsock system calls, but I don't need it for this one, because if it fails, it fails, and nothing needs to be done about it. The resulting local IP Address that the program attempts to generate from it won't be usable, and the program will recognize this, and simply report to the user that his address couldn't be determined. The success or failure of the call isn't really relevant to the path along which the program proceeds, so I excluded it, but like you said, it works either way so most beginners should indeed use it. I may edit the code afer this post to change that for clarity and consistency's sake.

As for your implied question about why I use that UByte Pointer method for getting the dot-format IPv4 address instead of the integrated Inet_ntoa function, it's mostly because I wanted to use a cross-platform, universal command that would work not only on Winsock but also under SDL_NET, which has no inet_ntoa equivalent command. If I ever posted a parallel SDL_NET tutorial (using the same chat program) I wanted all the corresponding commands to line up with each other consistently, and they all pretty much would, except for Inet_ntoa which doesn't exist at all under SDL_NET. So I used a "raw data extraction" technique, drawing the IP address out directly from the 4-byte UInteger representing it (by way of a UByte pointer to that UInteger) which will work under both platforms, rather than Inet_ntoa, which would only be available under Winsock.

But again you're right.. for an isolated Winsock-only beginner who's not concerned with platform-versatile methods, Inet_ntoa is the more common and usual command to learn and use, so I may edit that as well to reflect standard Winsock convention.
Ryan wrote: (And I guess a third question... do you know anything about the pointer warnings your program gets at compile? They show up in mine as well, like with GetHostName using a string it says we're passing a different pointer type. Any clues?)
Well, two answers on that one. For the one you mentioned, GetHostName actually wants a ZString rather than just a regular string, so that might explain FB complaining about the misfeed. Strangely I don't actually get a warning for that particular one, but maybe that's just due to the version I'm using.

For the other ones, to me it looks like FB doesn't like us using pseudo-pointers to Sockaddr_In variables in system calls. The four warning-level-0's I get on compile for my chat program are all for instances where I've cheated and used the pseudo-pointer @SA (where SA is a Sockaddr_In) instead of actually bothering to create a seperate Sockaddr_In Ptr that refers to the location of SA. That method is tolerated and accepted by FB everywhere else for all other types of variable pseudo-pointers and commands, but Sockaddr_In pseudo-pointers within a system call appears to generate the warning every time. Not sure whether the devs did that for a reason I don't know about, or whether it's just an overlooked quirk.

I'm way too tired right now but I'll post an update once I've made any desired edits to the above program source...
Joakim_ar
Posts: 36
Joined: Jun 05, 2005 20:48

Post by Joakim_ar »

Thanks for posting this guys, I'm looking forward to learn from it :)
cenozoite
Posts: 243
Joined: Aug 21, 2005 21:41

Post by cenozoite »

You're quite welcome... any other questions don't hesitate to ask. Meanwhile a couple of edit updates regarding the program source above:

1. I've edited the Gethostname command to include the return value, even though it isn't really needed in this particular instance. As Ryan pointed out, it is the more standard textbook way of using that command, so it's been modified for the benefit of beginners.

2. I've changed the way the program handles the subsequent data from the Gethostname/Gethostbyname commands as well, once again to reflect more standard Winsock methods for the benefit of beginners. The Inet_ntoa command is now implemented for getting the dot-format IP Address. My previous method is still there, but ghosted out with comments just for interest's sake.

3. An additional unrelated edit is that the program no longer sends blank/empty chat messages to the remote user, if the local user just hits enter without typing anything.

All other comments/suggestions/questions continue to be welcome...
Torahteen
Posts: 91
Joined: Jul 15, 2005 15:58
Contact:

Post by Torahteen »

Hey. The code won't work for me. At this line of code:

Code: Select all

FD_ZERO (@fdset)
I get this error:

Code: Select all

Expected pointer, before: 'fd_count'
I downloaded v0.15b and installed it (I think, I just copied the files and then pasted into my FB directory, then clicked Yes to All when it asked to replace a file).
cenozoite
Posts: 243
Joined: Aug 21, 2005 21:41

Post by cenozoite »

It's because you also need the updated Winsock.bi file that comes in the Inc\Win folder for 0.15b. It's not in the the 0.15 downoad, so you have to access it through CVS. If you aren't familiar with CVS, I'll post a download link for just that one header file in here below. If any of the devs object, just let me know and I'll remove it. Download the file and replace the old winsock.bi file with it. You will have to right-click on the link and select Save-As to get it.


Winsock.bi 0.15 version
Torahteen
Posts: 91
Joined: Jul 15, 2005 15:58
Contact:

Post by Torahteen »

I'm getting 404 error. I'm not familiar with CVS
cenozoite
Posts: 243
Joined: Aug 21, 2005 21:41

Post by cenozoite »

Instead of left-clicking on the link in my message above, right-click on it and choose "save (link) target as" and it should let you download winsock.bi
Torahteen
Posts: 91
Joined: Jul 15, 2005 15:58
Contact:

Post by Torahteen »

I don't have a windows.bi file. Argh, sorry. Guess it won't work. Why won't libraries work on my computer.
cenozoite
Posts: 243
Joined: Aug 21, 2005 21:41

Post by cenozoite »

Not windows.bi, winsock.bi Right-clicking on that link above and choosing save-as should let you get it, then just place it in your freebasic directory, in the subdirectory inc\win. There should already be an older winsock.bi file there to be replaced.
Torahteen
Posts: 91
Joined: Jul 15, 2005 15:58
Contact:

Post by Torahteen »

Ah yes, but in the header file for winsock, there is this:

Code: Select all

#include once "windows.bi"
Edit: BTW, thanks for helping me. I feel like I get annoying some times.
cenozoite
Posts: 243
Joined: Aug 21, 2005 21:41

Post by cenozoite »

No problem. Okay, yes I see that you do in fact need windows.bi as well, which goes in your Inc folder, not Inc\Win. Get it here, by right-clicking and choose Save-Target-As:

Windows.bi
Post Reply