Donald8282 Posted March 19, 2011 Share Posted March 19, 2011 Hello, I am making a simple Instant messenger and I have made the client without a problem. The server I'm having a bit of trouble with. I have made a server that can allow one person to connect and chat with me but I'm trying to get it so multiple people can connect. I have written some of the code for it but I am stuck. expandcollapse popupTCPStartup() Global $SERVER, $SOCKET $i = 0 Dim $SOCKET[?] $SERVER = TCPListen(@IPAddress1,1337) If @error Then MsgBox("Error to listening on port 1337.") Quit() EndIf While 1 sleep(10) $TConn = TCPAccept($SERVER) If $TConn <> -1 Then $SOCKET[$i] = $TConn $i += 1 EndIf For $Cx = 0 to $i $RECV = TCPRecv($SOCKET[$i], 512) If $RECV <> "" Then sendall() EndIf Next WEnd Func sendall() $DATA = $RECV If $DATA <> "" Then For $Cx = 0 to $i TCPSend($SOCKET[$Cx], $DATA) Next EndIf EndFunc Func Quit() For $Cx = 0 to $i TCPCloseSocket($SOCKET[$Cx]) Next TCPShutdown() Exit EndFunc I don't know how to use arrays very well so this is a problem for me. If anyone could help in any way like push me in the right direction or help me out with the arrays I'd be thankful. Thanks in adv. Link to comment Share on other sites More sharing options...
bwochinski Posted March 19, 2011 Share Posted March 19, 2011 (edited) I made a few tweaks to your code, enough I think to get it basically functional. In this kind of application, I would prefer the array UDF functions, as I did below (ie: _arrayAdd and _arrayDelete ). Looking through the help doc on a few of the functions I added should be a decent starting point. And feel free to ask if you have any particular questions. expandcollapse popup#include <Array.au3> TCPStartup() Global $SERVER, $SOCKET[1] $SERVER = TCPListen(@IPAddress1,1337) If @error Then MsgBox(0,"error","Error to listening on port 1337.") Quit() EndIf While 1 sleep(25) $TConn = TCPAccept($SERVER) If $TConn <> -1 Then _ArrayAdd($SOCKET,$TConn) EndIf For $Cx = 0 to UBound($SOCKET) - 1 If $SOCKET[$Cx] <> "" Then $RECV = TCPRecv($SOCKET[$Cx], 512) If $RECV <> "" Then sendall($RECV) EndIf EndIf Next WEnd Func sendall($msg) If $msg <> "" Then For $Ox = 0 to UBound($SOCKET) - 1 If $SOCKET[$Ox] <> "" Then If TCPSend($SOCKET[$Ox], $msg) == 0 And @error Then TCPCloseSocket($SOCKET[$Ox]) _ArrayDelete($SOCKET,$Ox) EndIf EndIf Next EndIf EndFunc Func Quit() For $Qx = 0 to UBound($SOCKET) - 1 TCPCloseSocket($SOCKET[$Qx]) Next TCPShutdown() Exit EndFunc Edited March 19, 2011 by bwochinski Link to comment Share on other sites More sharing options...
Donald8282 Posted March 19, 2011 Author Share Posted March 19, 2011 (edited) Thank you so much =]. I suck at arrays and this is practically the first time I have tried TCP. Would you like to help me test this? I can upload the client. Edited March 19, 2011 by Donald8282 Link to comment Share on other sites More sharing options...
bwochinski Posted March 19, 2011 Share Posted March 19, 2011 Thank you so much =]. I suck at arrays and this is practically the first time I have tried TCP. Would you like to help me test this? I can upload the client.I would (with source anyway), but the network I'm on right now is heavily fire-walled, so the chances of my being able to connect to anything are about nil.For a simple test yourself you should be able to just run 2 instances of the client and see your messages propagate from one to the other. Link to comment Share on other sites More sharing options...
gigi1 Posted March 19, 2011 Share Posted March 19, 2011 hi, i started with TCP about a week ago, i had the same problemsi suggest to look at this example: the $0, $00 variables are quite confusing, but everything else is clear and well-commente.that's where i startedgigi1 Link to comment Share on other sites More sharing options...
Donald8282 Posted March 19, 2011 Author Share Posted March 19, 2011 Thanks Gigi1, I do have another problem now. I don't know how to have people "disconnect" from the server. I need it to close their socket on the server side. I am using the server that bwochinski has helped me with. The way I was thinking about trying would close every socket and I don't know how I would target just the one socket that was being closed. Link to comment Share on other sites More sharing options...
gigi1 Posted March 19, 2011 Share Posted March 19, 2011 (edited) hi, you need to have client's sockets store in different variables. i use a 2 dimensional array to make everything easier (for me at least ) here's a small example of how my server is structured note that it will NOT work alone, there are some undefined user functions ("out" stamps to console, "ProcessData"... processes data ) expandcollapse popup;Socket[0][0] contains the number of connected clients ;Socket[n][0] contains the Main connection socket identifier of the client n ;Socket[n][1] contains the Public IP of the client ;Socket[n][2] contains the Local IP of the client ;Socket[n][3] contains the computer name of the client ;Socket[n][4] contains the ping timer of the client ;Socket[n][5] contains the Connection timer of the client ;Socket[n][6] contains the connection status of the client: 0 means offline, 1 means connected While 1 Sleep(10) AcceptNewConnection() If ReceiveConnection() = 1 Then ProcessData() WEnd ;Func AcceptNewConnection() ;calls to TCPAccept, the processes request. ;Returns 1 if a new client connected, returns 0 otherwise. Func AcceptNewConnection() Local $TCPAccept = TCPAccept($ListeningSocket) If $Socket[0][0] = $MaxClients Then Out("A client tryed to connect, but client max number has beed reached") TCPCloseSocket($TCPAccept) Return 0 EndIf If $TCPAccept = -1 Then Return 0 ;no new connection -> return For $client_processing=1 To $MaxClients ;find the first open socket, assign new client to that socket If $Socket[$client_processing][0] = 0 Then $Socket[$client_processing][0] = $TCPAccept $Socket[0][0] = $Socket[0][0] + 1 Out("New Client Connected - assigned on Client "&$client_processing) Return 1 EndIf Next EndFunc ;Func ReceiveConnection() ;calls to TCPRecv for every connected client, checks connection if there are errors ;Returns 1 if some data is received, returns 0 otherwise Func ReceiveConnection() For $client_processing=1 To $MaxClients ;receive connection for every client (even disconnected ones) $ReceivedData = TCPRecv($Socket[$client_processing][0], 1000000) ;TCPRecv If @error <> 0 And $Socket[$client_processing][6] = 1 Then ;if there's an error (=no active socket) then close that TCPCloseSocket($Socket[$client_processing][0] ;close socket For $i=0 To 6 Step 1 ;reset the array of the client processing $Socket[$client_processing][$i]=0 Next Return -1 EndIf If $ReceivedData <> "" Then ;if $ReceivedData actually contains something then execute the ProcessData func Return 1 EndIf Next Return 0 EndFunc EDIT: i saw the server by bwochinsky, you can add a check for error just after TCPRecv, if there are errors connection is inactive, and you can close the socket Edited March 19, 2011 by gigi1 Link to comment Share on other sites More sharing options...
bwochinski Posted March 20, 2011 Share Posted March 20, 2011 EDIT: i saw the server by bwochinsky, you can add a check for error just after TCPRecv, if there are errors connection is inactive, and you can close the socketGood point, I didn't add a check on the TCPRecv function. I only had bad sockets thrown out after the TCPSend failed in the "sendall()" function.If you're wanting to really make this a more robust server, you'll need to implement some sort of chat protocol where you can send messages from the client to the server about things like connections, disconnections, chat messages, and user nicknames. A good exercise along this line might be to create a basic IRC server, since the IRC protocol is pretty simple itself but very useful. Link to comment Share on other sites More sharing options...
Donald8282 Posted March 20, 2011 Author Share Posted March 20, 2011 (edited) Good point, I didn't add a check on the TCPRecv function. I only had bad sockets thrown out after the TCPSend failed in the "sendall()" function. If you're wanting to really make this a more robust server, you'll need to implement some sort of chat protocol where you can send messages from the client to the server about things like connections, disconnections, chat messages, and user nicknames. A good exercise along this line might be to create a basic IRC server, since the IRC protocol is pretty simple itself but very useful. I already have something like that. Client: expandcollapse popup#Include <GUIConstantsEx.au3> #include <EditConstants.au3> #include <WindowsConstants.au3> #include <ButtonConstants.au3> #include <Misc.au3> Global $username = InputBox("Username", "What would you like your username to be?") $login = 0 TCPStartup() Global $CONNECT $CONNECT = TCPConnect("" ,1337) If @error Then MsgBox(16, "Error", "Cannot connect to '' on port 1337.") Quit() EndIf GUICreate("Donald's Instant Messenger", 300, 300) GUISetState() Global $info = GUICtrlCreateEdit("", 10, 10, 280, 200, BitOR($ES_AUTOVSCROLL, $ES_READONLY, $ES_WANTRETURN, $WS_VSCROLL), $WS_EX_STATICEDGE) GUICtrlSetBkColor(-1, 0xFFFFFF) Global $sending = GUICtrlCreateInput("", 10, 220, 200, 70) $b_send = GUICtrlCreateButton("Send", 220, 220, 70, 70, BitOR($BS_DEFPUSHBUTTON, $WS_GROUP)) TCPSend($CONNECT, "[" & @Hour & ":" & @MIN & ":" & @SEC & "] " & $username & " has connected.") While True $RECV = TCPRecv($CONNECT,512) If @error Then Quit() If $RECV <> "" Then GUICtrlSetData($info, $RECV & @CRLF, True) EndIf If $RECV = "MSG~SHUTDOWN" Then GUIDelete() MsgBox(0, "Shutting down", "The server has shut down.") Exit EndIf $msg = GUIGetMsg() Select Case $msg = $GUI_EVENT_CLOSE Quit() Case $msg = $b_send say() EndSelect WEnd Func say() $DATA = GUICtrlRead($Sending) If $DATA <> "" Then TCPSend($CONNECT, "[" & @Hour & ":" & @MIN & ":" & @SEC & "] " & $username & ": " & $DATA) GUICtrlSetData($sending, "") EndIf EndFunc Func Quit() TCPSend($CONNECT, "[" & @Hour & ":" & @MIN & ":" & @SEC & "] " & $username & " has disconnected.") sleep(50) TCPCloseSocket($CONNECT) ; Close socket TCPShutdown() Exit EndFunc Edited March 20, 2011 by Donald8282 Link to comment Share on other sites More sharing options...
bwochinski Posted March 20, 2011 Share Posted March 20, 2011 I already have something like that. That's a start, but the issue with implementing that client side is that I can kick everyone off your server with this script: $CONNECT = TCPConnect("your server ip" ,1337) While 1 TCPSend($CONNECT,"MSG~SHUTDOWN") Sleep(5000) WEnd Link to comment Share on other sites More sharing options...
Donald8282 Posted March 20, 2011 Author Share Posted March 20, 2011 That's a start, but the issue with implementing that client side is that I can kick everyone off your server with this script: $CONNECT = TCPConnect("your server ip" ,1337) While 1 TCPSend($CONNECT,"MSG~SHUTDOWN") Sleep(5000) WEnd Oh, yeah... I forgot to take that out. I was testing that with something else. Thanks for showing me that. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now