So I am creating UNet multiplayer application but i came to a problem while receiving message.
Application is for android but I also built it for computer.
When I run Server through unity editor and connect to it with client from computer I have part of code to test connection and send message and it is working and send message when player connects.
When I connect with phone it doesn't send message.
What I know is on phone it return NetworkTransport.Connect() value as 1 which means that it connected, but I do not think it connected it and i will explain it after code.
Here is my server code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using System.Text;
public class Server : MonoBehaviour
{
private const int MAX_CONNECTION = 100;
private int port = 7777;
private int hostId;
private int webHostId;
private int reliableChannel;
private int unreliableChannel;
private bool isStarted;
private byte error;
private void Start ()
{
NetworkTransport.Init();
ConnectionConfig cc = new ConnectionConfig();
reliableChannel = cc.AddChannel(QosType.Reliable);
unreliableChannel = cc.AddChannel(QosType.Unreliable);
HostTopology topology = new HostTopology(cc, MAX_CONNECTION);
hostId = NetworkTransport.AddHost(topology, port, null);
webHostId = NetworkTransport.AddWebsocketHost(topology, port, null);
isStarted = true;
}
private void Update()
{
if(!isStarted) { return; }
int recHostId;
int connectionId;
int channelId;
byte[] recBuffer = new byte[1024];
int bufferSize = 1024;
int dataSize;
byte error;
NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
switch(recData)
{
case NetworkEventType.Nothing:
break;
case NetworkEventType.ConnectEvent:
Debug.Log("Player " + connectionId + " has connected");
break;
case NetworkEventType.DataEvent:
string msg = Encoding.Unicode.GetString(recBuffer, 0, dataSize);
Debug.Log("Player " + connectionId + " has sent: " + msg);
break;
case NetworkEventType.DisconnectEvent:
Debug.Log("Player " + connectionId + " has disconnected");
break;
}
}
}
And here is Client Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class Client : MonoBehaviour
{
private const int MAX_CONNECTION = 100;
private int port = 7777;
private int hostId;
private int webHostId;
private int reliableChannel;
private int unreliableChannel;
private int connectionId;
private float connectionTime;
private bool isConnected;
private bool isStarted = false;
private byte error;
private string playerName;
public Text text;
public void Connect()
{
string pName = GameObject.Find("NameInput").GetComponent<InputField>().text;
if(pName == "")
{
Debug.Log("You must enter a name!");
return;
}
playerName = pName;
NetworkTransport.Init();
ConnectionConfig cc = new ConnectionConfig();
reliableChannel = cc.AddChannel(QosType.Reliable);
unreliableChannel = cc.AddChannel(QosType.Unreliable);
HostTopology topology = new HostTopology(cc, MAX_CONNECTION);
hostId = NetworkTransport.AddHost(topology, 0);
connectionId = NetworkTransport.Connect(hostId, "127.0.0.1", port, 0, out error);
connectionTime = Time.time;
isConnected = true;
}
private void Update()
{
if(!isConnected) { return; }
int recHostId;
int connectionId;
int channelId;
byte[] recBuffer = new byte[1024];
int bufferSize = 1024;
int dataSize;
byte error;
NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
switch(recData)
{
case NetworkEventType.Nothing:
break;
case NetworkEventType.ConnectEvent:
break;
case NetworkEventType.DataEvent:
break;
case NetworkEventType.DisconnectEvent:
break;
}
}
}
Here is how i tested application step by step.
For this testing i implemented line which change button text to connectionId which is connectionId = NetworkTransport.Connect(hostId, "127.0.0.1", port, 0, out error); and it comes right after that line
Build application as .exe (for pc)
Build and run application as .apk (for android) Run application inside editor (android build) - Server scene (which has server script)
Run application on android and pc as clients - Client scene (which has client script)
Input name and press Connect on PC client - inside unity console pops Player 1 has connected
Input name and press Connect on Android client - nothing happens inside unity but button text changes to 1 (which means it connected)
Again press Connect on PC Client (which add another client) and it should be player 3 since on android connection returned positive but instead it returns Player 2 has connected
I have no idea what is happening. Is there i need to do for android to connect or maybe because i am connecting with wifi (it was working normally with unity Network Manager but now i can not do it with Lower Api)
After performing all those tasks in the comment section, below are the possible reasons why this is not working:
1.NetworkTransport.Connect(hostId, "127.0.0.1", port, 0, out error);
If you run this on Android, it will try to connect to your Android device instead of your PC. You need to change "127.0.0.1" to the IP of your PC so that your Android device can connect to that.
Once you get that working, consider using NetworkDiscovery to automatically find the IP of the other device then connect to it.
2.Make sure that both devices(Android) and PC are connected to the-same network/Wi-Fi.
3.Firewall
The firewall on your computer can block incoming connections. You need to add Unity Editor or the built exe program if you are running your server from the standalone program into exceptions in the Firewall program so that it will allow incoming connections. Just Google "Allow programs through firewall" and you will find so many ways to do this.
Related
So I'm new to Unity and need to make a multiplayer game where I could sync clients with the interface on the Game server, I've created a Client and a server and the client do connect to the server but the problem is that it couldn't send messages, all that server receive is Null
I'm running the server as an application and the client need to be a WebGL
This is my Server.cs :
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public class server : MonoBehaviour
{
private const int MAX_CONNECTIONS = 2000;
private const string SERVER_IP = "192.168.1.8";
private const int SERVER_PORT = 8999;
private const int SERVER_WEB_PORT = 8998;
private const int BUFFER_SIZE = 400000;
private int reliablechannelid;
private int unreliablechannelid;
private int hostId;
private int webHosted;
private byte[] buffer = new byte[BUFFER_SIZE];
private bool isInit;
// Start is called before the first frame update
void Start()
{
GlobalConfig config = new GlobalConfig();
NetworkTransport.Init(config);
ConnectionConfig cc = new ConnectionConfig();
reliablechannelid = cc.AddChannel(QosType.Reliable);
unreliablechannelid = cc.AddChannel(QosType.Unreliable);
HostTopology topo = new HostTopology(cc, MAX_CONNECTIONS);
hostId = NetworkTransport.AddHost(topo, SERVER_PORT);
webHosted = NetworkTransport.AddWebsocketHost(topo, SERVER_WEB_PORT);
isInit = true;
}
//This function is called when data is sent
void OnData(int hostId, int connectionId, int channelId, byte[] data, int size, NetworkError error)
{
//Here the message being received is deserialized and output to the console
Stream serializedMessage = new MemoryStream(data);
BinaryFormatter formatter = new BinaryFormatter();
string message = formatter.Deserialize(serializedMessage).ToString();
//Output the deserialized message as well as the connection information to the console
Debug.Log("OnData(hostId = " + hostId + ", connectionId = "
+ connectionId + ", channelId = " + channelId + ", data = "
+ message + ", size = " + size + ", error = " + error.ToString() + ")");
Debug.Log("data = " + message);
}
// Update is called once per frame
void Update()
{
{
if (!isInit)
{
return;
}
int outHostId;
int outConnectionId;
int outChannelId;
byte[] buffer = new byte[1024];
int receivedSize;
byte error;
//Set up the Network Transport to receive the incoming message, and decide what type of event
NetworkEventType eventType = NetworkTransport.Receive(out outHostId, out outConnectionId, out outChannelId, buffer, buffer.Length, out receivedSize, out error);
switch (eventType)
{
//Use this case when there is a connection detected
case NetworkEventType.ConnectEvent:
{
//Call the function to deal with the received information
Debug.Log("Connected");
break;
}
//This case is called if the event type is a data event, like the serialized message
case NetworkEventType.DataEvent:
{
//Call the function to deal with the received data
OnData(outHostId, outConnectionId, outChannelId, buffer, receivedSize, (NetworkError)error);
break;
}
case NetworkEventType.Nothing:
break;
default:
//Output the error
Debug.LogError("Unknown network message type received: " + eventType);
break;
}
}
}
}
This is my Client.cs :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using UnityEngine.UI;
using System.IO;
public class client : MonoBehaviour
{
private const int MAX_CONNECTIONS = 2000;
private const string SERVER_IP = "192.168.1.7";
private const int SERVER_PORT = 8999;
private const int SERVER_WEB_PORT = 8998;
private const int BUFFER_SIZE = 400000;
private int connectionId;
private int reliablechannelid;
private int unreliableChannelId;
private int hostId;
bool ok;
private byte error;
// private byte[] buffer = new byte[BUFFER_SIZE];
private bool isConnected;
public string Msg = "test";
public byte[] buffer;
// Start is called before the first frame update
void Connect()
{
GlobalConfig config = new GlobalConfig();
NetworkTransport.Init(config);
ConnectionConfig cc = new ConnectionConfig();
reliablechannelid = cc.AddChannel(QosType.Reliable);
HostTopology topo = new HostTopology(cc, MAX_CONNECTIONS);
hostId = NetworkTransport.AddHost(topo, 0);
#if UNITY_WEBGL
connectionId = NetworkTransport.Connect(hostId, SERVER_IP, SERVER_WEB_PORT, 0, out error);
Debug.Log((NetworkError)error);
Debug.Log("connectionId= "+connectionId);
#else
connectionId = NetworkTransport.Connect(hostId, SERVER_IP, SERVER_PORT, 0, out error);
Debug.Log((NetworkError)error);
Debug.Log("connectionId= " + connectionId);
#endif
}
//This is the function that serializes the message before sending it
void SendMyMessage(string textInput)
{
byte error;
byte[] buffer = new byte[1024];
Stream message = new MemoryStream(buffer);
BinaryFormatter formatter = new BinaryFormatter();
//Serialize the message
formatter.Serialize(message, textInput);
//Send the message from the "client" with the serialized message and the connection information
NetworkTransport.Send(hostId, connectionId, reliablechannelid, buffer, (int)message.Position, out error);
//If there is an error, output message error to the console
if ((NetworkError)error != NetworkError.Ok)
{
Debug.Log("Message send error: " + (NetworkError)error);
}
}
// Update is called once per frame
void Update()
{
SendMyMessage("heyyyyy");
}
}
I have found the solution ,
i just added
NetworkTransport.Connect(hostId, SERVER_IP, SERVER_WEB_PORT, 0, out error);
to my server too , i didn't know that server need to be connected too
hope this will help someone
I'm trying to listen in on a host that's sending over UDP using MultiCastGroup. In Unity the client starts but no message is ever received, but if I take the exact same code and drop it into a console application it works and I see the host's messages.
Here's what I've got:
public class UDPListener : MonoBehaviour
{
IPEndPoint ip;
private int port = 20000;
private IPAddress group_address = IPAddress.Parse("233.255.255.255");
private UdpClient client;
string data;
private void Start()
{
StartClient();
}
void StartClient()
{
Debug.Log("Starting Client");
ip = new IPEndPoint(IPAddress.Any, port);
client = new UdpClient(ip);
client.JoinMulticastGroup(group_address);
client.BeginReceive(new AsyncCallback(ReceiveServerInfo), null);
}
void ReceiveServerInfo(IAsyncResult result)
{
byte[] receivedBytes = client.EndReceive(result, ref ip);
data = Encoding.ASCII.GetString(receivedBytes);
if (String.IsNullOrEmpty(data))
{
Debug.Log("No data received");
}
else
{
Debug.Log(data);
}
client.BeginReceive(new AsyncCallback(ReceiveServerInfo), null);
}
}
I've also had the same result using client.Receive (works in console application but not in Unity) so I'm wondering if there's maybe some Unity setting I'm missing?
Nevermind, Windows update had turned my firewall back on which was blocking Unity :]
I'm trying to send data from Unity to Raspberry Pi. I have succesfully connected them but I can't pass any data please help.
This is code that I use on the Raspberry side
import socket
backlog=1
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("169.254.242.100",50001))
s.listen(backlog)
try:
print ( "is waiting")
client, address = s.accept()
while 1:
data = client.recv(size)
if data:
tabela = data
print ( "sends data")
print (tabela[0])
client.send(data)
except:
print("closing socket")
client.close()
s.close()
and this is the one I use in Unity
using UnityEngine;
using System.Collections;
using System.Net.Sockets;
public class UnityToRaspberry : MonoBehaviour {
public string IP = "169.254.242.100"; //
public int Port = 50001;
public byte[] dane = System.Text.Encoding.ASCII.GetBytes("Hello");
public Socket client;
void Start(){
//dane [0] = 1;
client = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect (IP, Port);
if (client.Connected) {
Debug.Log ("Connected");
}
client.Send (dane);
}
void OnApplicationQuit(){
client.Close();
}
}
Thank You!
I bet you were super close! I've used your code plus an example from the Unity Answers[1]. This is what I have to establish a connection and transfer data between Unity 5.5.0f3 on Mac OSX Sierra and a Raspberry Pi 3 Model B via tcp sockets.
In Unity:
void setupSocket()
{
s.socketReady = false;
s.host = "192.20.20.2";
s.port = 50001;
try {
s.socket = new TcpClient(s.host, s.port);
s.stream = s.socket.GetStream();
s.writer = new StreamWriter(s.stream);
s.reader = new StreamReader(s.stream);
s.socketReady = true;
}
catch (Exception e) {
Debug.Log("Socket error:" + e);
}
}
void Update()
{
s.writer.Write("Hello Pi!");
s.writer.Flush();
}
Python on the Pi:
import socket
backlog = 1
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.20.20.2', 50001))
s.listen(backlog)
try:
print ("is waiting")
client, address = s.accept()
while 1:
data = client.recv(size)
if data:
print (data)
except:
print("closing socket")
client.close()
s.close()
sources: http://answers.unity3d.com/questions/601572/unity-talking-to-arduino-via-wifiethernet.html
https://docs.python.org/2/library/socket.html
I am trying to create a WPF form using Visual Studio C# that will interact with indicators I create for my trading charts in MultiCharts .Net
I've added a WPF Project to the solution and added the namespace for the indicators. However, I can not figure out how I can manipulate inputs for the indicator object. Any help from someone who works with this program would be much appreciated.
You have to create a local network connection to make this work--I used sockets, but anything in a similar way will support the same goal:
Make a new MC indicator like so:
public class tests_OwnApp : IndicatorObject {
public tests_OwnApp(object _ctx):base(_ctx)
{
PortNumber = 5000;
}
[Input]
public int PortNumber { get; set; }
public static string Symbol;
const string ServerIP = "127.0.0.1";
IPAddress localAdd;
TcpListener listener;
TcpClient client;
NetworkStream nwStrm;
private IPlotObject plot1;
protected override void Create() {
// create variable objects, function objects, plot objects etc.
plot1 = AddPlot(new PlotAttributes("", EPlotShapes.Line, Color.Red));
localAdd = IPAddress.Parse(ServerIP);
client = null;
}
protected override void StartCalc() {
// assign inputs
// establish connection
if (listener == null)
{
listener = new TcpListener(localAdd, PortNumber);
}
listener.Stop();
Thread.Sleep(100);
listener.Start();
}
protected override void CalcBar()
{
// indicator logic
if (Bars.LastBarTime <= Bars.Time[0] + new TimeSpan(2,0,0))
{
Symbol = Bars.Info.Name;
if (client == null || !client.Connected)
client = listener.AcceptTcpClient();
// create network stream
nwStrm = client.GetStream();
// send symbol to app:
Output.WriteLine("sending " + Symbol + " to application");
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(Symbol);
string closingPrice = Convert.ToString(Bars.Close[0]);
string totalMsg = "Sym," + Symbol +
"\nClose[0]," + closingPrice + "\nClose[1]," + Bars.Close[1].ToString();
byte[] bytes2 = ASCIIEncoding.ASCII.GetBytes(totalMsg);
nwStrm.Write(bytes2, 0, bytes2.Length);
}
}
}
In your app (Console App example, extends to WPF):
static void Main(string[] args)
{
const int PortNum = 5000;
const string ServerIP = "127.0.0.1";
DateTime startTime = DateTime.Now;
TcpClient client = new TcpClient(ServerIP, PortNum);
NetworkStream nwStream = client.GetStream();
while (true)
{
if (client.ReceiveBufferSize != 0)
{
nwStream = client.GetStream();
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
string msg = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead);
Console.WriteLine("received: " + msg);
if (DateTime.Now - new TimeSpan(0, 0, 30) > startTime)
{
break;
}
Thread.Sleep(100);
Console.Write("-ping-");
}
}
Console.ReadLine();
}
Run them both together and you'll find they connect and the info is received.
I used this example to get started, in case my example is not sufficient.
Be sure to include all the necessary namespaces:
using System.Net;
using System.Net.Sockets;
See the documentation I believe chapter three shows you how to work with indicators
I am in desperate need of help. I have essentially created a program that (will use) encryption to send messages back and forth. The encryption part is working fine, however I am fairly new to Threads and I can not for the life of me get my Client/Server pieces of the application to line up. The chat program is direct IP connection using TCP, so each host is a client and a server. The issue I appear to be having, when I debug, is that the server thread is either not ready when the Client tries to connect to it, or if it is ready it will not relinquish the Thread so the Client can connect! I have been working on this for hours and it is very frustrating.. I hope someone can help! I've included my code below.
This is my code snippet from my MainForm, which constructs the Client and Server aspects:
private void InitializeComponent() {
server = new ServerSide("127.0.0.1",7865);
servThread = new Thread(new ThreadStart(server.begin));
client = new ClientSide("127.0.0.1",7865);
clientThread = new Thread(new ThreadStart(client.begin));
servThread.Start();
clientThread.Start();
//servThread.Join();
//clientThread.Join();
}
This is my ServerSide code:
public class ServerSide
{
String IpString;
int tcpPort;
bool goodToGo = false;
System.Net.IPAddress ipAddress = null;
public ServerSide(String ip, int tcpPort)
{
IpString = ip;
bool isValidIp = System.Net.IPAddress.TryParse(IpString, out ipAddress);
if (isValidIp == true) // check if the IP is valid, set the bool to true if so
{
goodToGo = true;
}
else
{
goodToGo = false;
}
}
public void begin()
{
try
{
IPAddress ipAd = IPAddress.Parse(IpString);
/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, tcpPort);
Socket s = null;
/* Start Listening at the specified port */
while (true)
{
myList.Start();
if (myList.Pending())
{
s = myList.AcceptSocket();
break;
}
}
String toReceive = "";
while (true)
{
byte[] b = new byte[4096];
int k = s.Receive(b);
for (int i = 0; i < k; i++)
toReceive += Convert.ToString((Convert.ToChar(b[i])));
// ASCIIEncoding asen = new ASCIIEncoding();
var form = MainForm.ActiveForm as MainForm;
if (form != null)
{
form.messageReceived(toReceive);
}
toReceive = "";
}
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
}
ClientSide code:
public class ClientSide
{
private String IpString;
private int tcpPort;
private TcpClient tcpInt;
private static Stream stm;
private System.Net.IPAddress ipAddress = null;
private bool goodToGo = false;
public ClientSide(String ip, int tcpPort)
{
IpString = ip;
this.tcpPort = tcpPort;
bool isValidIp = System.Net.IPAddress.TryParse(IpString, out ipAddress);
if (isValidIp == true)
{
goodToGo = true;
}
else
{
goodToGo = false;
}
}
public void begin()
{
try
{
tcpInt = new TcpClient();
// Console.WriteLine("Connecting.....");
tcpInt.Connect(IpString, tcpPort);
// use the ipaddress as in the server program
// Console.WriteLine("Connected");
// String str = Console.ReadLine();
stm = tcpInt.GetStream();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
public void sendMessage(String str)
{
// stm = tcpInt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
stm.Write(ba, 0, ba.Length);
/** byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(bb[i]));*/
}
}
}
Once again.. what typically happens is my Client receives an error that the host actively refused the connection.. but I do not know how to time them. I am looking for how to have my server listening for TCP Connections, but still manage to go to my other thread to create the TCP Connecion to send the server (I am testing this on localhost currently).
Thanks.
In the constructor of the ServerSide class, you forgot to initialize the tcpPort member. Because you forgot, the server will try to listen to port 0 and the client will try to connect to port 7865, and it will fail.
Try adding this code to the constructor in the ServerSide class.
this.tcpPort = tcpPort;
As for the threads, you might have a problem if the client thread tries to connect before the server thread has started listening. You can use a loop to try to connect a number of times (let's say 10), with a timeout (let's say 1 second) if you don't succeed. This way, you will retry 10 times and give up after that.