Copy link to clipboard
Copied
I have a game in the works, and though I got the UDP to work perfectly, I sadly later found out that that is simply just a lossy protocol. There's apparently (as far as my knowledge goes) nothing you can do to make it resend data if the data was not received successfully by the recipient.
So, I was wondering how to use TCP? I've heard it's possible, but I can't seem to find a single tutorial or any information anywhere on how to do it. I found on Adobe's site socket connections, and though I got the server to connect (I think), I have no clue how to send data to it, how to get other clients to connect to it, etc. Any help?
This is the script I've been using, and though it does connect... that's basically all it does, I don't know where to go from here...
package
{
import flash.display.Sprite;
import flash.events.EventDispatcher;
import flash.events.Event;
import flash.events.*;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.ServerSocketConnectEvent;
import flash.net.ServerSocket;
import flash.net.Socket;
public class TCP extends Sprite
{
private var serverSocket:ServerSocket;
private var clientSockets:Array = new Array();
public function TCP()
{
try
{
// Create the server socket
serverSocket = new ServerSocket();
// Add the event listener
serverSocket.addEventListener( Event.CONNECT, connectHandler );
serverSocket.addEventListener( Event.CLOSE, onClose );
// Bind to local port 8087
serverSocket.bind( 8087, "127.0.0.1" );
// Listen for connections
serverSocket.listen();
trace( "Listening on " + serverSocket.localPort );
}
catch(e:SecurityError)
{
trace(e);
}
}
public function connectHandler(event:ServerSocketConnectEvent):void
{
//Thesocket is provided by the event object
var socket:Socket = event.socket as Socket;
clientSockets.push( socket );
socket.addEventListener( ProgressEvent.SOCKET_DATA, socketDataHandler);
socket.addEventListener( Event.CLOSE, onClientClose );
socket.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
//Send a connect message
socket.writeUTFBytes("Connected");
socket.flush();
trace( "Sending connect message" );
}
public function socketDataHandler(event:ProgressEvent):void
{
var socket:Socket = event.target as Socket
//Read the message from the socket
var message:String = socket.readUTFBytes( socket.bytesAvailable );
trace( "Received: " + message);
// Echo the received message back to the sender
message = "Echo -- " + message;
socket.writeUTFBytes( message );
socket.flush();
trace( "Sending: " + message );
}
private function onClientClose( event:Event ):void
{
trace( "Connection to client closed." );
//Should also remove from clientSockets array...
}
private function onIOError( errorEvent:IOErrorEvent ):void
{
trace( "IOError: " + errorEvent.text );
}
private function onClose( event:Event ):void
{
trace( "Server socket closed by OS." );
}
}}
1 Correct answer
unless you're using a server that all players connect to, you should be using adobe's peer-to-peer networking (rtmfp).
Copy link to clipboard
Copied
unless you're using a server that all players connect to, you should be using adobe's peer-to-peer networking (rtmfp).
Copy link to clipboard
Copied
Thank you, I actually just found some documents online (one a server, one a client) and got the client to connect, as long as the server is on the same computer. I tried putting the server on one computer and a client on the other but the connection failed... is there something I'm missing here?
Here's an example of the client's script:
sock.connect('127.0.0.1',8910);
// receive data from socket
function onSocketData(e:ProgressEvent):void
{
trace(sock.bytesAvailable + ' byte(s) available');
// read the socket data
if (sock.bytesAvailable > 0)
{
// (I know it's a string for this example)
var msg:String = sock.readUTFBytes(sock.bytesAvailable);
trace(msg);
if (msg == 'Connected.')
{
// send a message back to the server (which it will return to me to confirm it worked)
sock.writeUTFBytes('Thanks for connecting!');
gotoAndStop(2);
}
// flush!
sock.flush();
}
}
Thank you.
Copy link to clipboard
Copied
you'll need to use the correct ip for the non-local client.
Copy link to clipboard
Copied
Alright, I looked up that the IP to connect to the LAN for the server is supposed to be like this:
serverSocket.bind( 8080, "192.168.1.4" );
But I get this error:
Error #2002: Operation attempted on invalid socket.
It seems to only work when I set it to:
(8910, '127.0.0.1');
What's going on here?
Copy link to clipboard
Copied
test from a non-local computer. ie, a file server.
otherwise you're probably encountering a cross-domain security issue.
Copy link to clipboard
Copied
Alright thank you for all the info, was very helpful. I have one more question though, it seems that the method I've been told to use: sock.writeUTFBytes('message'); seems to only send back to the socket the message was originally from, rather than sending the message to multiple clients from the server... I was wondering if there was a simple way to tweak the code to do this, or do I need a new method entirely? Again, thanks!!
Copy link to clipboard
Copied
again: unless you're using a server that all players connect to, you should be using adobe's peer-to-peer networking (rtmfp).
ie, with multiplayer each player can communicate with a server and the server communicates with each player, or you use peer-to-peer communication. below is an excerpt from a book i wrote (Flash Game Development: In a Social, Mobile and 3D World).
Social Gaming - Multiplayer Games
With multiplayer games, data needs to be communicated among the players. When a player makes a move (changing the game state) the updated game state needs to be communicated to all the other players. In addition, that communication needs to occur in a timely manner.
With turn-based games (like card games) that communication among players can take as long as few seconds without degrading the game experience. With real time games (like shooter games), even a 250 millisecond delay in communicating game state leads to a significantly degraded player experience. Consequently, real time multiplayer games require substantial expertise to successfully develop and deploy.
There are two fundamentally different ways that communication among players can be accomplished. Players can communicate via a server (server-based games) or they can communicate directly from player to player (peer-to-peer) games.
Server Based Multiplayer Games
Generally, the code in each player’s Flash game handles the player’s input, transmits player data to the server, receives other players' data and displays the game state. The server receives player data, validates the data, updates and maintains game state and transmits each player’s data to the other players.
The code used on the server cannot be ActionScript so you will need to learn a server-side coding language like php or c#. Server-side coding is beyond the scope of this book so I will not cover server-based multiplayer games except to say you need to have advanced coding skills in, at least, two languages (ActionScript and a server-side language) to create these game types.
Peer-to-peer games
Since Flash Player 10, you can create multiplayer games without the need of an intermediary server to facilitate player communication. The Flash Player can use a protocol (Adobe's Real-Time Media Flow Protocol) that allows direct peer-to-peer communication.
Instead of using server-side code to handle the game logic and coordinate game state among players, each peer in the network handles their own game logic and game state and communicates that directly to their peers and each peer updates their game state based on the data received from others.
To use peer-to-peer networking each peer must connect with an Adobe server. Peer-to-peer communication does not go through that server (or it that would not be peer-to-peer) but peers must stay connected with the Adobe server in order to communicate with each other.
To communicate with the Adobe server you should use your own server URL and developer key. That URL and key can be obtained at http://www.adobe.com/cfusion/entitlement/index.cfm?e=cirrus.
Below is a simple tic-tac-toe game that uses Adobe's peer-to-peer networking to pair-up players. The NetConnection class is used to establish a connection to the Adobe server while the NetGroup class is used for peer-to-peer communication.
I used only a small part of the NetGroup methods for the tic-tac-toe game but there are more available if you are sharing data among many users and/or sharing large amounts of data.
The tic-tac-toe game is in support files/Chapter 11/multiplayer and is extensively commented
Copy link to clipboard
Copied
Right, I got an AIR socket server that they're supposed to connect to, and so far it works with the client on the same machine the server is. I have used RTMFP but it was way too lossy, unless there's a way to fix that I want to use the server.
Copy link to clipboard
Copied
is your server your local computer?
is the problem client on your local computer?
Copy link to clipboard
Copied
Yes, the server is a simple AIR application on my local computer.
Copy link to clipboard
Copied
see if removing security issues helps, Adobe - Flash Player : Settings Manager - Global Security Settings panel
Copy link to clipboard
Copied
Alright, I'll try that, but I do have one more question, it seems when I try to send a signal to the other client, it simply sends the signal BACK to the client that sent the message... I understand this isn't an error in the programming, because the method I'm using is apparently SUPPOSED to do that, I just have to find out how I'm supposed to make sure the signal sends to ALL the clients instead of just back to the sender, do you have any ideas?
Copy link to clipboard
Copied
the message will be sent to the server. then it's up to the server to send that message to everyone else.
Copy link to clipboard
Copied
Right, but what code is used for the server to send the message to everyone else? When I use
socket.writeUTFBytes('whatever');
socket.flush();
It just sends it back to the sender rather than everyone connected to the server. I don't know how to get it to send to everyone. Is there a simple way to do this or do I have to manually set something up for the server to keep track of multiple clients?
Copy link to clipboard
Copied
what's 'whatever'???
you need to an array of users. google a tutorial on whatever server you're using.
Copy link to clipboard
Copied
'whatever' is just whatever the message is, a string, for example.
And I will try, I have been Googling allover the place for tutorials but they're hard to find, however, thank you, you have been very helpful.
Copy link to clipboard
Copied
you're welcome.
Copy link to clipboard
Copied
I got it figured out!!
To get it to send to all the clients (sockets), I just had to put this into the server at the line where it sends over the UTFBytes:
for each (var socket:Socket in clientSockets)
{
socket.writeUTFBytes(message);
socket.flush();
}
Of course, I also had an array set up: var clientSockets:Array = new Array();
Also, to get it to connect to my LAN, I actually had to REMOVE the IP address in the server, so it connects with: serverSocket.bind(8080);
Then, with the client, I connect it to the server using: sock.connect('localhost',8080);

