Reputation: 13
I made super simple game on plain C# using Windows Forms to learn a little bit about making programs "talk" over internet. Server and client are on same program and user just chooses which one he is by clicking a button.
It currently works just as I want as long as server and client are both ran on same PC using ip 127.0.0.1 to connect. If I try to use internal or external ip (port is opened) it doesn't work anymore ("Before Accept" triggers, but "Before Receive" doesn't).
I got base for my code from Darryl Braaten who answered someone elses question: create c# asynchronous socket client in multithreaded environment
AsyncServer.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
namespace blockbattle
{
public class AsyncServer
{
private const int port = 11000;
public int clientID = -1;
public string serverPos = "";
public string clientPos = "";
public string newBullets = "";
public bool bulletsSent = false;
public string receivedBullets = "";
public void StartServer()
{
Thread thread = new Thread(Run) { IsBackground = true };
thread.Start();
}
private void Run()
{
Debug.WriteLine("Running");
TcpListener tcpListener = new TcpListener(IPAddress.Loopback, port);
tcpListener.Start();
while (true)
{
Debug.WriteLine("Before Accept");
ServerState state = new ServerState { WorkSocket = tcpListener.AcceptSocket() };
Debug.WriteLine("Before Receive");
Receive(state);
}
}
private void Receive(ServerState state)
{
state.WorkSocket.BeginReceive(state.Buffer, 0, ServerState.BufferSize, 0, ReceiveCallBack, state);
}
private void ReceiveCallBack(IAsyncResult ar)
{
ServerState state = (ServerState)ar.AsyncState;
try
{
int byteReceived = state.WorkSocket.EndReceive(ar);
if (byteReceived > 0)
{
string receivedString = Encoding.UTF8.GetString(state.Buffer, 0, byteReceived);
string[] receivedData = receivedString.Split('+');
clientID = int.Parse(receivedData[0]);
clientPos = receivedData[1];
if (receivedData[2].Length > 0)
receivedBullets = receivedData[2];
byte[] bytesToSend = Encoding.UTF8.GetBytes(string.Format("{0}+{1}", serverPos, newBullets));
if (newBullets.Length > 0)
{
newBullets = "";
bulletsSent = true;
}
Array.Copy(bytesToSend, state.Buffer, bytesToSend.Length);
state.WorkSocket.Send(state.Buffer, 0, bytesToSend.Length, SocketFlags.None);
Array.Clear(state.Buffer, 0, state.Buffer.Length);
Receive(state);
}
}
catch (Exception e)
{
Debug.Print(e.ToString());
}
}
private class ServerState
{
public const int BufferSize = 1024;
public readonly byte[] Buffer = new byte[BufferSize];
public Socket WorkSocket = null;
}
}
}
AsyncClient.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
namespace blockbattle
{
public partial class AsyncClient
{
private const int port = 11000;
private readonly int _clientId;
private readonly Random _random;
public string clientPos = "";
public string serverPos = "";
public string newBullets = "";
public bool bulletsSent = false;
public string receivedBullets = "";
public string lastBullet = "";
public AsyncClient(int clientId)
{
_clientId = clientId;
_random = new Random(clientId);
}
public void StartClient(IPAddress serverIP)
{
try
{
Socket workSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ClientState state = new ClientState { WorkSocket = workSocket };
workSocket.BeginConnect(new IPEndPoint(serverIP, port), ConnectCallBack, state);
}
catch (Exception ex)
{
Debug.Print(ex.Message);
}
}
private void ConnectCallBack(IAsyncResult ar)
{
ClientState state = (ClientState)ar.AsyncState;
state.WorkSocket.EndConnect(ar);
Send(state);
}
private void Receive(ClientState clientState)
{
clientState.WorkSocket.BeginReceive(clientState.Buffer, 0, ClientState.BufferSize, 0, ReceiveCallBack, clientState);
}
private void ReceiveCallBack(IAsyncResult ar)
{
ClientState state = (ClientState)ar.AsyncState;
Socket client = state.WorkSocket;
int byteReceived = client.EndReceive(ar);
if (byteReceived > 0)
{
string receivedString = Encoding.UTF8.GetString(state.Buffer, 0, byteReceived);
string[] receivedData = receivedString.Split('+');
serverPos = receivedData[0];
if (receivedData[1].Length > 0)
receivedBullets = receivedData[1];
Array.Clear(state.Buffer, 0, state.Buffer.Length);
Thread.Sleep(33);
Send(state);
}
}
private void Send(ClientState clientState)
{
byte[] buffer = Encoding.UTF8.GetBytes(string.Format("{0}+{1}+{2}", _clientId, clientPos, newBullets));
if (newBullets.Length > 0)
{
newBullets = "";
bulletsSent = true;
}
try
{
clientState.WorkSocket.BeginSend(buffer, 0, buffer.Length, 0, BeginSendCallBack, clientState);
}
catch (Exception ex)
{
Debug.Print(ex.Message);
}
}
private void BeginSendCallBack(IAsyncResult ar)
{
ClientState state = (ClientState)ar.AsyncState;
int byteSent = state.WorkSocket.EndSend(ar);
Receive(state);
}
}
public class ClientState
{
// Client socket.
public Socket WorkSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] Buffer = new byte[BufferSize];
public int Count = 0;
}
}
Upvotes: 1
Views: 902