How to close a TCP connection by port? - sockets

I would like to close an existing connection between to application running on my server.
If you have a suggestion please reply on how to program this, you will be appreciated.
Note that: TCPView application can close the connection exactly as I need, but I would like to run it as a console application or other command line.

Finally I found the solution for my request.
Credit goes to CSharpFriends.com, now migrated to debugging.com.
The following windows API should be used:
//API to get list of connections
[DllImport("iphlpapi.dll")]
private static extern int GetTcpTable(IntPtr pTcpTable, ref int pdwSize, bool bOrder);
//API to change status of connection
[DllImport("iphlpapi.dll")]
private static extern int SetTcpEntry(IntPtr pTcprow);
//Convert 16-bit value from network to host byte order
[DllImport("wsock32.dll")]
private static extern int ntohs(int netshort);
//Convert 16-bit value back again
[DllImport("wsock32.dll")]
private static extern int htons(int netshort);
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;
namespace ConnectionManager
{
class Disconnector
{
}
public class Starter
{
public static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("Disconnect IP1 [IP2 [IP3 [IPn]]]");
Console.WriteLine("");
Console.WriteLine("Connections up now:");
string[] cons = Disconnecter.Connections(Disconnecter.State.Established);
foreach (string s in cons)
{
Console.WriteLine(s);
}
}
else
{
foreach (string s in args)
{
Disconnecter.CloseLocalIP(s);
Disconnecter.CloseRemoteIP(s);
}
}
}
}
public class Disconnecter
{
/// <summary>
/// Enumeration of the states
/// </summary>
public enum State
{
/// <summary> All </summary>
All = 0,
/// <summary> Closed </summary>
Closed = 1,
/// <summary> Listen </summary>
Listen = 2,
/// <summary> Syn_Sent </summary>
Syn_Sent = 3,
/// <summary> Syn_Rcvd </summary>
Syn_Rcvd = 4,
/// <summary> Established </summary>
Established = 5,
/// <summary> Fin_Wait1 </summary>
Fin_Wait1 = 6,
/// <summary> Fin_Wait2 </summary>
Fin_Wait2 = 7,
/// <summary> Close_Wait </summary>
Close_Wait = 8,
/// <summary> Closing </summary>
Closing = 9,
/// <summary> Last_Ack </summary>
Last_Ack = 10,
/// <summary> Time_Wait </summary>
Time_Wait = 11,
/// <summary> Delete_TCB </summary>
Delete_TCB = 12
}
/// <summary>
/// Connection info
/// </summary>
private struct MIB_TCPROW
{
public int dwState;
public int dwLocalAddr;
public int dwLocalPort;
public int dwRemoteAddr;
public int dwRemotePort;
}
//API to get list of connections
[DllImport("iphlpapi.dll")]
private static extern int GetTcpTable(IntPtr pTcpTable, ref int pdwSize, bool bOrder);
//API to change status of connection
[DllImport("iphlpapi.dll")]
//private static extern int SetTcpEntry(MIB_TCPROW tcprow);
private static extern int SetTcpEntry(IntPtr pTcprow);
//Convert 16-bit value from network to host byte order
[DllImport("wsock32.dll")]
private static extern int ntohs(int netshort);
//Convert 16-bit value back again
[DllImport("wsock32.dll")]
private static extern int htons(int netshort);
/// <summary>
/// Testexample
/// </summary>
public static void TEST()
{
Console.WriteLine("Not Working Yet!!!");
//string[] ret = Connections(State.All);
//foreach (string con in ret) if (con.IndexOf("192.168.0.101") > -1) System.Diagnostics.Debug.WriteLine(con);
//System.Diagnostics.Debug.WriteLine("----------------------------");
//CloseRemotePort(1863);
//CloseRemotePort(80);
//ret = Connections(State.All);
//foreach (string con in ret) if (con.IndexOf("192.168.0.101") > -1) System.Diagnostics.Debug.WriteLine(con);
}
/// <summary>
/// Close all connection to the remote IP
/// </summary>
/// <param name="IP">IPen på remote PC</param>
public static void CloseRemoteIP(string IP)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (rows[i].dwRemoteAddr == IPStringToInt(IP))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Close all connections at current local IP
/// </summary>
/// <param name="IP"></param>
public static void CloseLocalIP(string IP)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (rows[i].dwLocalAddr == IPStringToInt(IP))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Closes all connections to the remote port
/// </summary>
/// <param name="port"></param>
public static void CloseRemotePort(int port)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (port == ntohs(rows[i].dwRemotePort))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Closes all connections to the local port
/// </summary>
/// <param name="port"></param>
public static void CloseLocalPort(int port)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (port == ntohs(rows[i].dwLocalPort))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Close a connection by returning the connectionstring
/// </summary>
/// <param name="connectionstring"></param>
public static void CloseConnection(string connectionstring)
{
try
{
//Split the string to its subparts
string[] parts = connectionstring.Split('-');
if (parts.Length != 4) throw new Exception("Invalid connectionstring - use the one provided by Connections.");
string[] loc = parts[0].Split(':');
string[] rem = parts[1].Split(':');
string[] locaddr = loc[0].Split('.');
string[] remaddr = rem[0].Split('.');
//Fill structure with data
MIB_TCPROW row = new MIB_TCPROW();
row.dwState = 12;
byte[] bLocAddr = new byte[] { byte.Parse(locaddr[0]), byte.Parse(locaddr[1]), byte.Parse(locaddr[2]), byte.Parse(locaddr[3]) };
byte[] bRemAddr = new byte[] { byte.Parse(remaddr[0]), byte.Parse(remaddr[1]), byte.Parse(remaddr[2]), byte.Parse(remaddr[3]) };
row.dwLocalAddr = BitConverter.ToInt32(bLocAddr, 0);
row.dwRemoteAddr = BitConverter.ToInt32(bRemAddr, 0);
row.dwLocalPort = htons(int.Parse(loc[1]));
row.dwRemotePort = htons(int.Parse(rem[1]));
//Make copy of the structure into memory and use the pointer to call SetTcpEntry
IntPtr ptr = GetPtrToNewObject(row);
int ret = SetTcpEntry(ptr);
if (ret == -1) throw new Exception("Unsuccessful");
if (ret == 65) throw new Exception("User has no sufficient privilege to execute this API successfully");
if (ret == 87) throw new Exception("Specified port is not in state to be closed down");
if (ret != 0) throw new Exception("Unknown error (" + ret + ")");
}
catch (Exception ex)
{
throw new Exception("CloseConnection failed (" + connectionstring + ")! [" + ex.GetType().ToString() + "," + ex.Message + "]");
}
}
/// <summary>
/// Gets all connections
/// </summary>
/// <returns></returns>
public static string[] Connections()
{
return Connections(State.All);
}
/// <summary>
/// Gets a connection list of connections with a defined state
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public static string[] Connections(State state)
{
MIB_TCPROW[] rows = getTcpTable();
ArrayList arr = new ArrayList();
foreach (MIB_TCPROW row in rows)
{
if (state == State.All || state == (State)row.dwState)
{
string localaddress = IPIntToString(row.dwLocalAddr) + ":" + ntohs(row.dwLocalPort);
string remoteaddress = IPIntToString(row.dwRemoteAddr) + ":" + ntohs(row.dwRemotePort);
arr.Add(localaddress + "-" + remoteaddress + "-" + ((State)row.dwState).ToString() + "-" + row.dwState);
}
}
return (string[])arr.ToArray(typeof(System.String));
}
//The function that fills the MIB_TCPROW array with connectioninfos
private static MIB_TCPROW[] getTcpTable()
{
IntPtr buffer = IntPtr.Zero; bool allocated = false;
try
{
int iBytes = 0;
GetTcpTable(IntPtr.Zero, ref iBytes, false); //Getting size of return data
buffer = Marshal.AllocCoTaskMem(iBytes); //allocating the datasize
allocated = true;
GetTcpTable(buffer, ref iBytes, false); //Run it again to fill the memory with the data
int structCount = Marshal.ReadInt32(buffer); // Get the number of structures
IntPtr buffSubPointer = buffer; //Making a pointer that will point into the buffer
buffSubPointer = (IntPtr)((int)buffer + 4); //Move to the first data (ignoring dwNumEntries from the original MIB_TCPTABLE struct)
MIB_TCPROW[] tcpRows = new MIB_TCPROW[structCount]; //Declaring the array
//Get the struct size
MIB_TCPROW tmp = new MIB_TCPROW();
int sizeOfTCPROW = Marshal.SizeOf(tmp);
//Fill the array 1 by 1
for (int i = 0; i < structCount; i++)
{
tcpRows[i] = (MIB_TCPROW)Marshal.PtrToStructure(buffSubPointer, typeof(MIB_TCPROW)); //copy struct data
buffSubPointer = (IntPtr)((int)buffSubPointer + sizeOfTCPROW); //move to next structdata
}
return tcpRows;
}
catch (Exception ex)
{
throw new Exception("getTcpTable failed! [" + ex.GetType().ToString() + "," + ex.Message + "]");
}
finally
{
if (allocated) Marshal.FreeCoTaskMem(buffer); //Free the allocated memory
}
}
private static IntPtr GetPtrToNewObject(object obj)
{
IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(obj));
Marshal.StructureToPtr(obj, ptr, false);
return ptr;
}
//Convert an IP string to the INT value
private static int IPStringToInt(string IP)
{
if (IP.IndexOf(".") < 0) throw new Exception("Invalid IP address");
string[] addr = IP.Split('.');
if (addr.Length != 4) throw new Exception("Invalid IP address");
byte[] bytes = new byte[] { byte.Parse(addr[0]), byte.Parse(addr[1]), byte.Parse(addr[2]), byte.Parse(addr[3]) };
return BitConverter.ToInt32(bytes, 0);
}
//Convert an IP integer to IP string
private static string IPIntToString(int IP)
{
byte[] addr = System.BitConverter.GetBytes(IP);
return addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3];
}
}
}

close(fd); /* comment to reach minimum size for an answer */

Related

Multi-Client Chat and file transfer in linux

\I want to make a socket application that will run on Linux and provide multiple messaging and file transfer. Can you share sample code? Can you help me i am a second year computer engineering student?
I found a similar code in my research, but I cannot connect to my linux server from different computers.I learned this code from github #HondaPL.
This is client codes
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Collections.Generic;
using MessengerLogic;
using System.IO;
namespace Messenger
{
public class Connection
{
public static int BufferSize = 1024;
public static string nick;
public static IPAddress ip = IPAddress.Parse("-.-.-.-");
public static int port = 1234;
public static TcpClient client = new TcpClient();
public static List<string> users = new List<string>();
public static bool isEnd = false;
public static string[] fromServer = new string[30];
public void Connect(string nickname)
{
nick = nickname;
client.Connect(ip, port);
nickname += "$Welcome$";
byte[] buffer = Encoding.ASCII.GetBytes(nickname);
NetworkStream ns = client.GetStream();
Console.WriteLine(nickname);
ns.Write(buffer, 0, buffer.Length);
Thread thread = new Thread(o => ReceiveData((TcpClient)o));
thread.Start(client);
}
static void ReceiveData(TcpClient client)
{
NetworkStream ns = client.GetStream();
byte[] receivedBytes = new byte[1024];
int byte_count;
StringParser parser = new StringParser();
while ((byte_count = ns.Read(receivedBytes, 0, receivedBytes.Length)) > 0)
{
fromServer = new string[30];
users.Clear();
string message = Encoding.ASCII.GetString(receivedBytes, 0, byte_count);
fromServer = parser.Parser(message);
if (fromServer[0] == "List")
{
for (int i = 1; i < fromServer.Length; i++)
{
users.Add(fromServer[i]);
}
isEnd = true;
}
else
{
Console.WriteLine(message);
Console.WriteLine(fromServer[0]);
Console.WriteLine(fromServer[1]);
FrmOnlineUsers.frm.AssignValues(fromServer[0], fromServer[1]);
FrmOnlineUsers.frm.MessageFromClient();
}
}
}
public List<string> Refresh()
{
NetworkStream ns = client.GetStream();
string temp = nick;
temp += "$List$";
byte[] buffer = ASCIIEncoding.ASCII.GetBytes(temp);
ns.Write(buffer, 0, buffer.Length);
while (!isEnd)
{
}
isEnd = false;
return users;
}
public void SendMessage(string who, string msg)
{
NetworkStream ns = client.GetStream();
string temp = $"{who}$Message${msg}$";
byte[] buffer = ASCIIEncoding.ASCII.GetBytes(temp);
ns.Write(buffer, 0, buffer.Length);
}
public void FileSend(string filepath, string nick, string fileName)
{
NetworkStream ns = client.GetStream();
FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);
byte[] bytesToSend = new byte[fs.Length];
int numBytesRead = fs.Read(bytesToSend, 0, bytesToSend.Length);
int totalBytes = 0;
//Tutaj trzeba dodać, aby pobierał nazwę pliku
string temp = $"{nick}$File${fileName}${fs.Length}";
byte[] buffer = ASCIIEncoding.ASCII.GetBytes(temp);
ns.Write(buffer, 0, buffer.Length);
Thread.Sleep(1000);
for (int i = 0; i <= fs.Length / BufferSize; i++)
{
if (fs.Length - (i * BufferSize) > BufferSize)
{
ns.Write(bytesToSend, i * BufferSize,
BufferSize);
totalBytes += BufferSize;
}
else
{
ns.Write(bytesToSend, i * BufferSize,
(int)fs.Length - (i * BufferSize));
totalBytes += (int)fs.Length - (i * BufferSize);
}
}
fs.Close();
}
}
}

How to display text in Unity game

I inherited by my ex collegue a Unity game. Now I need to implement this behaviour. The game consist in a car drive by user using Logitech steering.
Now I need to show a Text every X minute in a part of the screen like "What level of anxiety do you have ? " Ad the user should to set a value from 0 to 9 using the Logitech steering but I really don't know where to start.
This is my manager class:
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
namespace DrivingTest
{
// Braking test Manager
public class BtManager : BaseTestManger
{
// Public variables
public BreakCar breakCar;
public float minBrakeThreshold = 0.2f;
internal int vehicalSpeed;
internal int noOfEvents;
internal float durationOfTest;
// Private variables
private IRDSPlayerControls playerControlCar;
protected int xSpeed;
protected int ySpeed;
private float brakeEventStartTime;
private float brakeEventDifferenceTime;
private SafetyDistanceCheck safetyDistanceCheck;
protected float totalSafetyDistance;
protected int totalSafetyDistanceCount;
private List<float> averageEventReactionTime = new List<float>();
#region Init
// Use this for initialization
public override void Start()
{
base.Start();
playerControlCar = car.GetComponent<IRDSPlayerControls>();
safetyDistanceCheck = car.GetComponent<SafetyDistanceCheck>();
}
public override void OnEnable()
{
base.OnEnable();
BreakCar.BrakeStart += BrakeCarEvent;
BreakCar.BrakeEventEnd += CallTestOver;
}
public override void OnDisable()
{
base.OnDisable();
BreakCar.BrakeStart -= BrakeCarEvent;
BreakCar.BrakeEventEnd -= CallTestOver;
}
protected override void SetUpCar()
{
car.AddComponent<SelfDriving>();
}
#endregion
/// <summary>
/// Calls the main Test over method.
/// </summary>
private void CallTestOver()
{
GameManager.Instance.Testover();
}
protected override void OnSceneLoaded(eTESTS test)
{
UiManager.Instance.UpdateInstructions(Constants.BT_INSTRUCTION);
}
protected override void GetApiParams()
{
NextTestOutput nextTestOutput = GameManager.Instance.currentTest;
if (nextTestOutput.content != null && nextTestOutput.content.Count > 0)
{
foreach (var item in nextTestOutput.content[0].listInputParameter)
{
switch ((ePARAMETERS)item.id)
{
case ePARAMETERS.X_SPEED:
xSpeed = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.Y_SPEED:
ySpeed = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.SPEED_OF_VEHICLE:
vehicalSpeed = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.NUMBER_OF_EVENTS:
noOfEvents = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.DURATION_OF_TEST:
durationOfTest = float.Parse(item.Value) * 60; //converting minutes into seconds
break;
}
}
SetupBrakeCar();
}
}
protected virtual void SetupBrakeCar()
{
DOTween.Clear();
durationOfTest = noOfEvents * Random.Range(10,20); // The random value is the time between two consecutive tests.
breakCar.SetInitalParams(new BrakeCarInit
{
carMaxSpeed = vehicalSpeed * 0.95f,
durationOfTest = durationOfTest,
noOfEvents = noOfEvents,
xSpeed = xSpeed,
ySpeed = ySpeed
});
breakCar.distanceCheck = true;
}
protected override void SubmitRestultToServer()
{
SubmitTest submitTest = new SubmitTest
{
outputParameters = new List<SaveOutputParameter>
{
new SaveOutputParameter
{
id = (int)ePARAMETERS.OUT_REACTION_TIME,
value = ((int)(GetEventReactionTimeAvg () * Constants.FLOAT_TO_INT_MULTIPLAYER)).ToString()
},
new SaveOutputParameter
{
id = (int)ePARAMETERS.OUT_AVG_RT,
value = GetReactionResult().ToString()
}
}
};
WebService.Instance.SendRequest(Constants.API_URL_FIRST_SAVE_TEST_RESULT, JsonUtility.ToJson(submitTest), SubmitedResultCallback);
}
protected override void ShowResult()
{
UiManager.Instance.UpdateStats(
(
"1. " + Constants.EVENT_REACTION + (GetEventReactionTimeAvg() * Constants.FLOAT_TO_INT_MULTIPLAYER).ToString("0.00") + "\n" +
"2. " + Constants.REACTION_TIME + reactionTest.GetReactionTimeAvg().ToString("0.00")
));
}
public void LateUpdate()
{
//Debug.Log("TH " + .Car.ThrottleInput1 + " TH " + playerControlCar.Car.ThrottleInput + " brake " + playerControlCar.Car.Brake + " brake IP " + playerControlCar.Car.BrakeInput);
//Debug.Log("BrakeCarEvent "+ brakeEventStartTime + " Player car " + playerControlCar.ThrottleInput1 + " minBrakeThreshold " + minBrakeThreshold);
if (brakeEventStartTime > 0 && playerControlCar.Car.ThrottleInput1 > minBrakeThreshold)
{
brakeEventDifferenceTime = Time.time - brakeEventStartTime;
Debug.Log("Brake event diff " + brakeEventDifferenceTime);
Debug.Log("Throttle " + playerControlCar.Car.ThrottleInput1);
averageEventReactionTime.Add(brakeEventDifferenceTime);
brakeEventStartTime = 0;
safetyDistanceCheck.GetSafetyDistance(SafetyDistance);
}
}
private void SafetyDistance(float obj)
{
totalSafetyDistance += obj;
++totalSafetyDistanceCount;
}
/// <summary>
/// Records the time when the car ahead starts braking
/// </summary>
protected void BrakeCarEvent()
{
brakeEventStartTime = Time.time;
Debug.Log("BrakeCarEvent ");
}
/// <summary>
/// calculates the average time taken to react
/// </summary>
public float GetEventReactionTimeAvg()
{
float avg = 0;
foreach (var item in averageEventReactionTime)
{
avg += item;
}//noofevents
return avg / (float)averageEventReactionTime.Count;
}
}
}
EDIT
I create new class FearTest:
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace DrivingTest
{
public class FearTest : MonoBehaviour
{
//public GameObject redDot;
public TextMeshPro textAnsia2;
public TextMesh textAnsia3;
public int shouldEvaluateTest = 0; // 0 - false, 1 - true
public int secondsInterval;
public int secondsToDisaply;
public int radiusR1;
public int radiusR2;
public int reactionTestDuration;
public int maxDots;
public float dotRadius = 1;
private float endTime;
private float dotDisaplyAtTime;
private List<float> dotDisplayReactTime = new List<float>();
private int missedSignals;
private int currentDotsCount;
private bool isReactionAlreadyGiven;
public bool ShouldEvaluateTest
{
get
{
return shouldEvaluateTest != 0;
}
}
void OnEnable()
{
GameManager.TestSceneLoaded += OnSceneLoaded;
}
private void OnDisable()
{
GameManager.TestSceneLoaded -= OnSceneLoaded;
}
#region Scene Loaded
private void OnSceneLoaded(eTESTS test)
{
if (SceneManager.GetActiveScene().name != test.ToString())
return;
Reset();
GetApiParams();
}
#endregion
private void GetApiParams()
{
#if UNITY_EDITOR
if (!GameManager.Instance)
{
Init();
return;
}
#endif
Debug.Log("called rt");
NextTestOutput nextTestOutput = GameManager.Instance.currentTest;
if (nextTestOutput.content != null && nextTestOutput.content.Count > 0)
{
foreach (var item in nextTestOutput.content[0].listInputParameter)
{
switch ((ePARAMETERS)item.id)
{
case ePARAMETERS.RT_ENABLE:
shouldEvaluateTest = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RT_DURATION:
reactionTestDuration = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_FREQ:
secondsInterval = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_MAX_COUNT:
maxDots = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_RADIUS_R1:
radiusR1 = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_RADIUS_R2:
radiusR2 = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_SIZE:
dotRadius = float.Parse(item.Value)/10f;
break;
case ePARAMETERS.RED_DOT_TIME:
secondsToDisaply = System.Convert.ToInt32(item.Value);
break;
}
}
Debug.Log("called rt "+ shouldEvaluateTest);
/*if (ShouldEvaluateTest)
{
Init();
}*/
Init();//dopo bisogna sistemare il shoudl evaluatetest
}
}
Coroutine displayCoroutine;
public void Init()
{
endTime = Time.time + reactionTestDuration + 10;
SetRedDotSize();
displayCoroutine = StartCoroutine(RedDotDisplay());
}
private IEnumerator RedDotDisplay()
{
yield return new WaitForSeconds(2);
while (true)
{
SetRandomDotPosition();
RedDot(true);
isReactionAlreadyGiven = false;
dotDisaplyAtTime = Time.time;
currentDotsCount++;
yield return new WaitForSeconds(secondsToDisaply);
if(!isReactionAlreadyGiven)
{
missedSignals++;
}
RedDot(false);
if ((reactionTestDuration > 0 && endTime <= Time.time) || (maxDots > 0 && currentDotsCount >= maxDots))
break;
float waitTime = secondsInterval - secondsToDisaply;
yield return new WaitForSeconds(waitTime);
}
}
private void Update()
{
if (!ShouldEvaluateTest)
return;
if (!isReactionAlreadyGiven && /*redDot.activeSelf &&*/ (LogitechGSDK.LogiIsConnected(0) && LogitechGSDK.LogiButtonIsPressed(0, 23)))
{
isReactionAlreadyGiven = true;
float reactionTime = Time.time - dotDisaplyAtTime;
Debug.Log("Reaction Time RT : " + reactionTime);
RedDot(false);
dotDisplayReactTime.Add(reactionTime);
}
}
public double GetReactionTimeAvg()
{
double avg = 0;
foreach (var item in dotDisplayReactTime)
{
avg += item;
}
//avg / currentDotsCount
return avg / (float)dotDisplayReactTime.Count;
}
public double GetMissedSignals()
{
return ((float) missedSignals / (float) currentDotsCount) * 100;
}
private void RedDot(bool state)
{
//redDot.SetActive(state);
textAnsia2.SetText("Pippo 2");
}
private void SetRedDotSize()
{
//redDot.transform.localScale *= dotRadius;
textAnsia2.transform.localScale *= dotRadius;
textAnsia3.transform.localScale *= dotRadius;
}
private void SetRandomDotPosition()
{
//redDot.GetComponent<RectTransform>().anchoredPosition = GetRandomPointBetweenTwoCircles(radiusR1, radiusR2)*scale;
float scale = ((Screen.height*0.9f) / radiusR2) * 0.9f;
Vector3 pos = GetRandomPointBetweenTwoCircles(radiusR1, radiusR2) * scale;
Debug.Log("RT temp pos : " + pos);
pos = new Vector3(500, 500, 0);
Debug.Log("RT pos : " + pos);
// redDot.transform.position = pos;
Vector3 pos2 = new Vector3(20, 20, 0);
Debug.Log("text ansia 2 : " + pos2);
textAnsia2.transform.position = pos2;
textAnsia3.transform.position = pos;
}
#region Getting Red Dot b/w 2 cricles
/*
Code from : https://gist.github.com/Ashwinning/89fa09b3aa3de4fd72c946a874b77658
*/
/// <summary>
/// Returns a random point in the space between two concentric circles.
/// </summary>
/// <param name="minRadius"></param>
/// <param name="maxRadius"></param>
/// <returns></returns>
Vector3 GetRandomPointBetweenTwoCircles(float minRadius, float maxRadius)
{
//Get a point on a unit circle (radius = 1) by normalizing a random point inside unit circle.
Vector3 randomUnitPoint = Random.insideUnitCircle.normalized;
//Now get a random point between the corresponding points on both the circles
return GetRandomVector3Between(randomUnitPoint * minRadius, randomUnitPoint * maxRadius);
}
/// <summary>
/// Returns a random vector3 between min and max. (Inclusive)
/// </summary>
/// <returns>The <see cref="UnityEngine.Vector3"/>.</returns>
/// <param name="min">Minimum.</param>
/// <param name="max">Max.</param>
Vector3 GetRandomVector3Between(Vector3 min, Vector3 max)
{
return min + Random.Range(0, 1) * (max - min);
}
#endregion
#region Reset
private void Reset()
{
if (displayCoroutine != null)
StopCoroutine(displayCoroutine);
RedDot(false);
shouldEvaluateTest = 0;
reactionTestDuration = 0;
secondsInterval = 0;
missedSignals = 0;
maxDots = 0;
radiusR1 = 0;
radiusR2 = 0;
dotRadius = 1;
secondsToDisaply = 0;
endTime = 0;
dotDisaplyAtTime = 0;
dotDisplayReactTime.Clear();
//redDot.transform.localScale = Vector3.one;
textAnsia2.transform.localScale = Vector3.one;
textAnsia3.transform.localScale = Vector3.one;
currentDotsCount = 0;
isReactionAlreadyGiven = true;
}
#endregion
}
}
When "SetRandomDotPosition" method is called, in my scene I can display in a random position of the screen the RedDot (that is a simple image with a red dot), but I m not able to display my textAnsia2. How can I fixed it ?
I hope this will help you to get started :
https://vimeo.com/709527359
the scripts:
https://imgur.com/a/csNKwEh
I hope that in the video i covered every step that i've made.
Edit: The only thing is for you to do is to make the input of the Wheel to work on the slider. Try to make a simple script: when the text is enabled then the input from a joystick to work on that . When is disabled switch it back for his purpose .

Azure Spatial Anchors / Unity World Anchors lose position

I am working on a simple unity app testing azure spatial anchors on the HoloLens. I started from this example (https://github.com/Azure/azure-spatial-anchors-samples) and changed it a little bit to create several anchors.
In some test sessions I experienced that the anchored objects lost their position suddenly and where moved about 10 meters or more.
As I unterstand HoloLens and mixed reality the camera position is tracked by kind of visual odometry or rather SLAM algorithms so it is normal that the pose of the device drifts over the time and so will the anchors do. But I did not expect such a huge shift.
Furthermore I expected the anchors to get back in places in the moment the features in the neighborhood of the anchors are visible again for the devices camera. But this is not always the case. Sometimes the anchors get back at their original position when the features are visible again, but sometimes this does not change anything about the wrong positions.
This is the code:
using Microsoft.Azure.SpatialAnchors;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.XR.WSA;
using UnityEngine.XR.WSA.Input;
using System.Linq;
using System.IO;
using UnityEditor;
public class AzureSpatialAnchorsScript : MonoBehaviour
{
/// <summary>
/// The sphere prefab.
/// </summary>
public GameObject spherePrefab;
/// <summary>
/// Set this string to the Spatial Anchors account id provided in the Spatial Anchors resource.
/// </summary>
protected string SpatialAnchorsAccountId = "xxxxxxxxxxxxxxxx";
/// <summary>
/// Set this string to the Spatial Anchors account key provided in the Spatial Anchors resource.
/// </summary>
protected string SpatialAnchorsAccountKey = "yyyyyyyyyyyyyyyyyyyyyyy";
/// <summary>
/// Our queue of actions that will be executed on the main thread.
/// </summary>
private readonly Queue<Action> dispatchQueue = new Queue<Action>();
/// <summary>
/// Use the recognizer to detect air taps.
/// </summary>
private GestureRecognizer recognizer;
protected CloudSpatialAnchorSession cloudSpatialAnchorSession;
/// <summary>
/// The CloudSpatialAnchor that we either 1) placed and are saving or 2) just located.
/// </summary>
protected CloudSpatialAnchor currentCloudAnchor;
/// <summary>
/// True if we are creating + saving an anchor
/// </summary>
protected bool tapExecuted = false;
/// <summary>
/// The IDs of the CloudSpatialAnchor that were saved. Use it to find the CloudSpatialAnchors
/// </summary>
protected Dictionary<string, GameObject> cloudSpatialAnchorIdsObjects = new Dictionary<string, GameObject> { };
protected IList<string> anchorIds = new List<string>();
/// <summary>
/// The sphere rendered to show the position of the CloudSpatialAnchor.
/// </summary>
protected Material sphereMaterial;
/// <summary>
/// Indicate if we are ready to save an anchor. We can save an anchor when value is greater than 1.
/// </summary>
protected float recommendedForCreate = 0;
private string pathName;
// Start is called before the first frame update
void Start()
{
Application.SetStackTraceLogType(LogType.Log, StackTraceLogType.None);
recognizer = new GestureRecognizer();
recognizer.StartCapturingGestures();
recognizer.SetRecognizableGestures(GestureSettings.Tap);
recognizer.Tapped += HandleTap;
InitializeSession();
string FileName = "ids.txt";
pathName = Path.Combine(Application.persistentDataPath, FileName);
getIds();
if (anchorIds.Count > 0)
{
CreateWatcher(anchorIds.ToArray());
}
}
// Update is called once per frame
void Update()
{
lock (dispatchQueue)
{
if (dispatchQueue.Count > 0)
{
dispatchQueue.Dequeue()();
}
}
}
/// <summary>
/// Queues the specified <see cref="Action"/> on update.
/// </summary>
/// <param name="updateAction">The update action.</param>
protected void QueueOnUpdate(Action updateAction)
{
lock (dispatchQueue)
{
dispatchQueue.Enqueue(updateAction);
}
}
/// <summary>
/// Cleans up objects.
/// </summary>
public void CleanupObjects()
{
if (cloudSpatialAnchorIdsObjects != null)
{
cloudSpatialAnchorIdsObjects = new Dictionary<string, GameObject>();
}
if (sphereMaterial != null)
{
Destroy(sphereMaterial);
sphereMaterial = null;
}
//currentCloudAnchor = null;
}
/// <summary>
/// Initializes a new CloudSpatialAnchorSession.
/// </summary>
void InitializeSession()
{
Debug.Log("ASA Info: Initializing a CloudSpatialAnchorSession.");
if (string.IsNullOrEmpty(SpatialAnchorsAccountId))
{
Debug.LogError("No account id set.");
return;
}
if (string.IsNullOrEmpty(SpatialAnchorsAccountKey))
{
Debug.LogError("No account key set.");
return;
}
cloudSpatialAnchorSession = new CloudSpatialAnchorSession();
cloudSpatialAnchorSession.Configuration.AccountId = SpatialAnchorsAccountId.Trim();
cloudSpatialAnchorSession.Configuration.AccountKey = SpatialAnchorsAccountKey.Trim();
cloudSpatialAnchorSession.LogLevel = SessionLogLevel.All;
cloudSpatialAnchorSession.Error += CloudSpatialAnchorSession_Error;
cloudSpatialAnchorSession.OnLogDebug += CloudSpatialAnchorSession_OnLogDebug;
cloudSpatialAnchorSession.SessionUpdated += CloudSpatialAnchorSession_SessionUpdated;
cloudSpatialAnchorSession.AnchorLocated += CloudSpatialAnchorSession_AnchorLocated;
cloudSpatialAnchorSession.LocateAnchorsCompleted += CloudSpatialAnchorSession_LocateAnchorsCompleted;
cloudSpatialAnchorSession.Start();
Debug.Log("ASA Info: Session was initialized.");
}
void CreateWatcher(string[] cloudSpatialAnchorIds)
{
Debug.Log("ASA Info: We will look for placeded anchors.");
// Create a Watcher to look for the anchor we created.
AnchorLocateCriteria criteria = new AnchorLocateCriteria();
criteria.Identifiers = cloudSpatialAnchorIds;
cloudSpatialAnchorSession.CreateWatcher(criteria);
Debug.Log("ASA Info: Watcher created. Number of active watchers: " + cloudSpatialAnchorSession.GetActiveWatchers().Count);
}
private void CloudSpatialAnchorSession_Error(object sender, SessionErrorEventArgs args)
{
Debug.LogError("ASA Error: " + args.ErrorMessage);
}
private void CloudSpatialAnchorSession_OnLogDebug(object sender, OnLogDebugEventArgs args)
{
Debug.Log("ASA Log: " + args.Message);
System.Diagnostics.Debug.WriteLine("ASA Log: " + args.Message);
}
private void CloudSpatialAnchorSession_SessionUpdated(object sender, SessionUpdatedEventArgs args)
{
Debug.Log("ASA Log: recommendedForCreate: " + args.Status.RecommendedForCreateProgress);
recommendedForCreate = args.Status.RecommendedForCreateProgress;
}
private void CloudSpatialAnchorSession_AnchorLocated(object sender, AnchorLocatedEventArgs args)
{
switch (args.Status)
{
case LocateAnchorStatus.Located:
Debug.Log("ASA Info: Anchor located! Identifier: " + args.Identifier);
QueueOnUpdate(() =>
{
// Create a green sphere.
GameObject spatialAnchorObj = GameObject.Instantiate(spherePrefab, Vector3.zero, Quaternion.identity) as GameObject;
spatialAnchorObj.AddComponent<WorldAnchor>();
sphereMaterial = spatialAnchorObj.GetComponent<MeshRenderer>().material;
sphereMaterial.color = Color.green;
// Get the WorldAnchor from the CloudSpatialAnchor and use it to position the sphere.
spatialAnchorObj.GetComponent<UnityEngine.XR.WSA.WorldAnchor>().SetNativeSpatialAnchorPtr(args.Anchor.LocalAnchor);
cloudSpatialAnchorIdsObjects.Add(args.Anchor.Identifier, spatialAnchorObj);
Debug.Log("Detected Pos: " + spatialAnchorObj.GetComponent<UnityEngine.XR.WSA.WorldAnchor>().transform.position.ToString("F4"));
Debug.Log("Detected Rot: " + spatialAnchorObj.GetComponent<UnityEngine.XR.WSA.WorldAnchor>().transform.rotation.ToString("F4"));
tapExecuted = false;
});
break;
case LocateAnchorStatus.AlreadyTracked:
Debug.Log("ASA Info: Anchor already tracked. Identifier: " + args.Identifier);
break;
case LocateAnchorStatus.NotLocated:
Debug.Log("ASA Info: Anchor not located. Identifier: " + args.Identifier);
break;
case LocateAnchorStatus.NotLocatedAnchorDoesNotExist:
Debug.LogError("ASA Error: Anchor not located does not exist. Identifier: " + args.Identifier);
break;
}
}
private void CloudSpatialAnchorSession_LocateAnchorsCompleted(object sender, LocateAnchorsCompletedEventArgs args)
{
Debug.Log("ASA Info: Locate anchors completed. Watcher identifier: " + args.Watcher.Identifier);
}
/// <summary>
/// Called by GestureRecognizer when a tap is detected.
/// </summary>
/// <param name="eventArgs">The tap.</param>
public void HandleTap(TappedEventArgs eventArgs)
{
if (tapExecuted)
{
return;
}
tapExecuted = true;
Debug.Log("ASA Info: We will create a new anchor.");
//// Clean up any anchors that have been placed.
//CleanupObjects();
// Construct a Ray using forward direction of the HoloLens.
Ray GazeRay = new Ray(eventArgs.headPose.position, eventArgs.headPose.forward);
// Raycast to get the hit point in the real world.
RaycastHit hitInfo;
Physics.Raycast(GazeRay, out hitInfo, float.MaxValue);
this.CreateAndSaveSphere(hitInfo.point);
}
/// <summary>
/// Creates a sphere at the hit point, and then saves a CloudSpatialAnchor there.
/// </summary>
/// <param name="hitPoint">The hit point.</param>
protected virtual void CreateAndSaveSphere(Vector3 hitPoint)
{
// Create a white sphere.
GameObject spatialAnchorObj = GameObject.Instantiate(spherePrefab, hitPoint, Quaternion.identity) as GameObject;
spatialAnchorObj.AddComponent<WorldAnchor>();
sphereMaterial = spatialAnchorObj.GetComponent<MeshRenderer>().material;
sphereMaterial.color = Color.white;
Debug.Log("ASA Info: Created a local anchor.");
// Create the CloudSpatialAnchor.
currentCloudAnchor = new CloudSpatialAnchor();
// Set the LocalAnchor property of the CloudSpatialAnchor to the WorldAnchor component of our white sphere.
WorldAnchor worldAnchor = spatialAnchorObj.GetComponent<WorldAnchor>();
if (worldAnchor == null)
{
throw new Exception("ASA Error: Couldn't get the local anchor pointer.");
}
// Save the CloudSpatialAnchor to the cloud.
currentCloudAnchor.LocalAnchor = worldAnchor.GetNativeSpatialAnchorPtr();
//cloudAnchor.AppProperties[#"x"] = #"frame";
//cloudAnchor.AppProperties[#"label"] = #"my latest picture";
Task.Run(async () =>
{
// Wait for enough data about the environment.
while (recommendedForCreate < 1.0F)
{
await Task.Delay(330);
}
bool success = false;
try
{
QueueOnUpdate(() =>
{
// We are about to save the CloudSpatialAnchor to the Azure Spatial Anchors, turn it yellow.
sphereMaterial.color = Color.yellow;
});
await cloudSpatialAnchorSession.CreateAnchorAsync(currentCloudAnchor);
success = currentCloudAnchor != null;
if (success)
{
// Record the identifier to locate.
string cloudAnchorId = currentCloudAnchor.Identifier;
QueueOnUpdate(() =>
{
// Turn the sphere blue.
sphereMaterial.color = Color.blue;
});
Debug.Log("ASA Info: Saved anchor to Azure Spatial Anchors! Identifier: " + cloudAnchorId);
//Debug.Log("Created " + cloudAnchorId + " at pos: " + worldAnchor.transform.position);
//Debug.Log("Created " + cloudAnchorId + "at rot: " + worldAnchor.transform.rotation);
anchorIds.Add(cloudAnchorId);
cloudSpatialAnchorIdsObjects.Add(cloudAnchorId, spatialAnchorObj);
WriteIds();
}
else
{
sphereMaterial.color = Color.red;
Debug.LogError("ASA Error: Failed to save, but no exception was thrown.");
}
}
catch (Exception ex)
{
QueueOnUpdate(() =>
{
sphereMaterial.color = Color.red;
});
Debug.LogError("ASA Error: " + ex.Message);
}
// Allow the user to tap again to clear state and look for the anchor.
tapExecuted = false;
});
}
void WriteIds()
{
try
{
string fileContent = ""
//= ReadString();
;
foreach (string id in anchorIds)
{
fileContent += id + Environment.NewLine;
}
using (StreamWriter writer = new StreamWriter(new FileStream(pathName, FileMode.OpenOrCreate, FileAccess.Write)))
{
writer.Write(fileContent);
}
}
catch (Exception e)
{
Debug.LogError(e);
}
}
void getIds()
{
try
{
StreamReader reader = new StreamReader(pathName);
string line;
while ((line = reader.ReadLine()) != null)
{
anchorIds.Add(line);
}
reader.Close();
}
catch (FileNotFoundException e)
{
Debug.LogWarning("No AnchorId file found");
}
}
}
Is something wrong with the way the anchors are created or is this normal behavior?
It is not surprising behavior that sometimes the anchors lose their position and it could be the case that some of the anchors are relocalized after tracking is recovered, but not all of them. It could be helpful to add a script to the object you create for the anchor that shows the tracking state of the anchor attached to it. Here is a sample:-
using System;
using UnityEngine;
using UnityEngine.XR.WSA;
public class ShowTrackingState : MonoBehavior
{
WorldAnchor worldAnchor = null;
Material renderMaterial = null;
bool isTracking = false;
void Start()
{
renderMaterial = gameObject.GetComponent<Renderer>().material;
}
void OnDestroy()
{
if (renderMaterial != null)
{
Destroy(renderMaterial);
}
}
void Update()
{
if (worldAnchor == null)
{
worldAnchor = gameObject.GetComponent<worldAnchor>();
}
if (worldAnchor == null)
{
isTracking = false;
}
else
{
isTracking = worldAnchor.isLocated;
}
renderMaterial.color = isTracking ? Color.red : Color.green;
}
}
Also, a gentle reminder, it is a common mistake to forget to hide one's account id and key when posting questions on forums; but it is not secure so you might want to remove that part from your code snippet in the question :-)

unity 3d error CS0118

I get this error:
Assets/initadmod.cs(25,2): error CS0118: Admob' is anamespace' but a type' was expected
Please copy this script to your MonoDevelop to see where is error.
using UnityEngine;
using System.Collections;
using Admob;
namespace Admob {
namespace GoogleMobileAds {
public class initadmod : MonoBehaviour {
public static initadmod instance;
// Use this for initialization
void Start () {
instance = this;
Debug.Log("start unity demo-------------");
initAdmob();
}
public string baner_Adr;
public string fullbaner_Adr;
public string baner_IOS ;
public string fullbaner_IOS ;
Admob ad;
//bool isAdmobInited = false;
void initAdmob()
{
string adUnitIdbaner ;
string adUnitIdfull ;
// isAdmobInited = true;
#if UNITY_EDITOR
adUnitIdbaner = "baner_Adr";
adUnitIdfull = "fullbaner_Adr";
#elif UNITY_ANDROID
adUnitIdbaner = baner_Adr;
adUnitIdfull = fullbaner_Adr;
#elif UNITY_5 || UNITY_IOS || UNITY_IPHONE
adUnitIdbaner = baner_IOS;
adUnitIdfull = fullbaner_IOS;
#else
adUnitIdbaner = baner_Adr;
adUnitIdfull = fullbaner_Adr;
#endif
ad = Admob.Instance();
ad.bannerEventHandler += onBannerEvent;
ad.interstitialEventHandler += onInterstitialEvent;
ad.rewardedVideoEventHandler += onRewardedVideoEvent;
ad.nativeBannerEventHandler += onNativeBannerEvent;
ad.initAdmob(adUnitIdbaner, adUnitIdfull);
// ad.setTesting(true);
Debug.Log("admob inited -------------");
}
public bool ShowBanerOnPlay;
public bool _ShowFullOnBackToMainMenu;
public bool _ShowFullNowOnOpenGame;
public int ShowFullOndie;
/// <summary>
/// hiện baner nhỏ góc trên màn hình lúc chạy
/// </summary>
public void ShowBanerOnPlayGame()
{
if (ShowBanerOnPlay)
{
ShowBaner();
}
}
/// <summary>
/// hiện baner lúc chết
/// sau Showfullondie số lần chết mới cho hiện
/// </summary>
public void ShowFullOnDie()
{
if (UImanager.uimanager.showbane >= ShowFullOndie-1)
{
showInterstitial();
UImanager.uimanager.showbane = 0;
}
}
/// <summary>
/// hiện qc khi đến menu chính
/// </summary>
public void ShowFullOnBackToMainMenu()
{
if (_ShowFullOnBackToMainMenu)
{
showInterstitial();
}
}
/// <summary>
/// hiện quảng cáo khi mới mở game ra khi hết mục dowload
/// </summary>
public void ShowFullNowOnOpenGame()
{
if (_ShowFullNowOnOpenGame)
{
showInterstitial();
}
}
void showInterstitial()
{
if (ad.isInterstitialReady())
{
ad.showInterstitial();
}
else
{
ad.loadInterstitial();
}
}
void ShowBaner()
{
Admob.Instance().showBannerRelative(AdSize.SmartBanner, AdPosition.TOP_CENTER, 0);
}
public void HideBaner()
{
Admob.Instance().removeBanner();
}
void onInterstitialEvent(string eventName, string msg)
{
Debug.Log("handler onAdmobEvent---" + eventName + " " + msg);
if (eventName == AdmobEvent.onAdLoaded)
{
Admob.Instance().showInterstitial();
}
}
void onBannerEvent(string eventName, string msg)
{
Debug.Log("handler onAdmobBannerEvent---" + eventName + " " + msg);
}
void onRewardedVideoEvent(string eventName, string msg)
{
Debug.Log("handler onRewardedVideoEvent---" + eventName + " " + msg);
}
void onNativeBannerEvent(string eventName, string msg)
{
Debug.Log("handler onAdmobNativeBannerEvent---" + eventName + " " + msg);
}
}
}
}
On line 25 you are declaring
Admob ad;
but Admob is a namespace, not a class, so you need to add the class to your declaration, maybe something like (this is just an example)
Admob.GoogleMobileAds.initadmod ad;

Unity2D: UNET transport layer API server script isn't messaging properly

I'm following a tutorial unity multiplayer (UNET) on YouTube but I'm getting different results compared to the guy in the video. You see I followed his tutorial to the tea, however in my server script within the update function I used a debug.log in the switch statement default function to tell me if i'm receiving invalid messaging, which I am. I think that my message isn't really being sent properly despite the fact that I followed the guy's tutorial carefully! Am I missing something in my server script?
This is my code:
public class ServerClient
{
public int connectionId;
public string playerName;
}
public class Server : MonoBehaviour {
private const int MAX_CONNECTION = 4;
private int port = 8888;
private int hostId;
private int webHostId;
private int reliableChannel;
private int unreliableChannel;
private bool isStarted = false;
private byte error;
private List<ServerClient> clients = new List<ServerClient>();
private void Start()
{
NetworkTransport.Init ();
ConnectionConfig cc = new ConnectionConfig ();
reliableChannel = cc.AddChannel (QosType.Reliable);
unreliableChannel = cc.AddChannel (QosType.Unreliable);
HostTopology topo = new HostTopology (cc, MAX_CONNECTION);
hostId = NetworkTransport.AddHost (topo, port); // null
Debug.Log ("Socket Open. hostId is: " + hostId);
webHostId = NetworkTransport.AddWebsocketHost (topo, port, null); //, 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.ConnectEvent: //2
Debug.Log ("Player " + connectionId + "has connected");
OnConnection (connectionId);
break;
case NetworkEventType.DataEvent: //3
string msg = Encoding.Unicode.GetString(recBuffer, 0, dataSize);
//Debug.Log("Player" + connectionId + " has sent : " + msg);
Debug.Log("Recieving from " + connectionId + " : " + msg);
string[] splitData = msg.Split ('|');
switch (splitData[0])
{
case "OnNameIs":
OnNameIs (connectionId, splitData [1]);
break;
default:
Debug.Log ("Invalid message: " + msg);
break;
}
break;
case NetworkEventType.DisconnectEvent: // 4
Debug.Log("Player " + connectionId + "has disconnected");
break;
}
}
private void OnConnection(int cnnId)
{
// This may add a thrid player
ServerClient c = new ServerClient();
c.connectionId = cnnId;
c.playerName = "TEMP";
clients.Add(c);
//So you might want to change this later
string msg = "AskName|" + cnnId + "|";
foreach (ServerClient sc in clients)
msg += sc.playerName + '%' + sc.connectionId + '|';
msg = msg.Trim ('|');
Send (msg, reliableChannel, cnnId);
}
private void OnNameIs(int cnnId, string playerName)
{
clients.Find (x => x.connectionId == cnnId).playerName = playerName;
Send ("CNN|" + playerName + '|' + cnnId, reliableChannel, clients);
}
private void Send(string message, int channelId, int cnnId)
{
List<ServerClient> c = new List<ServerClient>();
c.Add (clients.Find (x => x.connectionId == cnnId));
Send (message, channelId, c);
}
private void Send(string message, int channelId, List<ServerClient> c)
{
Debug.Log ("Sending : " + message);
byte[] msg = Encoding.Unicode.GetBytes (message);
foreach (ServerClient sc in c)
{
NetworkTransport.Send (hostId, sc.connectionId, channelId, msg, message.Length * sizeof(char), out error);
}
}
}
The below script is my client script:
public class Player
{
public string playerName;
public GameObject avatar;
public int connectionId;
}
public class Client : MonoBehaviour {
private const int MAX_CONNECTION = 4;
private int port = 8888; //5701
private int hostId;
private int webHostId;
private int connectionId;
private int ourClientId;
private int reliableChannel;
private int unreliableChannel;
private float connectionTime;
private bool isConnected = false;
private bool isStarted = false;
private byte error;
private string playerName;
public GameObject playerPrefab;
public List<Player> players = new List<Player>();
public void Connect()
{
//Does the player have a name?
//take this part out
string pName = GameObject.Find("NameInput").GetComponent<InputField>().text;
if (pName == "") {
Debug.Log ("you must enter a name");
return;
}
playerName = pName;
//
// place this is the Start fuction
NetworkTransport.Init ();
ConnectionConfig cc = new ConnectionConfig ();
reliableChannel = cc.AddChannel (QosType.Reliable);
unreliableChannel = cc.AddChannel (QosType.Unreliable);
HostTopology topo = new HostTopology (cc, MAX_CONNECTION);
hostId = NetworkTransport.AddHost (topo, 0);
//
byte error;
connectionId = NetworkTransport.Connect (hostId, "127.0.0.1", port, 0, out error);
Debug.Log ("Connection to server. ConnectionId: " + connectionId);
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.DataEvent: //1
string msg = Encoding.Unicode.GetString (recBuffer, 0, dataSize);
Debug.Log ("Recieving : " + msg);
string[] splitData = msg.Split ('|');
switch (splitData[0])
{
case "AskName":
OnAskName (splitData);
break;
case "CNN":
SpawnPlayer (splitData[1], int.Parse(splitData[2]));
break;
case "DC":
break;
default:
Debug.Log ("Invalid message: " + msg);
break;
}
break;
}
}
private void OnAskName(string[] data)
{
ourClientId = int.Parse (data [1]);
Send ("OnNameis|" + playerName, reliableChannel);
for (int i = 2; i < data.Length - 1; i++)
{
string[] d = data[i].Split('%');
SpawnPlayer(d[0], int.Parse(d[1]));
}
}
private void SpawnPlayer(string playerName, int cnnId)
{
GameObject go = Instantiate (playerPrefab) as GameObject;
Debug.Log ("Object has been spawn", go);
if (cnnId == ourClientId) // the problem //
{
GameObject.Find("Canvas").SetActive (false);
isStarted = true;
}
Player p = new Player ();
p.avatar = go;
p.playerName = playerName;
p.connectionId = cnnId;
p.avatar.GetComponentInChildren<TextMesh>().text = playerName;
players.Add (p);
}
private void Send(string message, int channelId)
{
Debug.Log ("Sending : " + message);
byte[] msg = Encoding.Unicode.GetBytes (message);
NetworkTransport.Send (hostId, connectionId, channelId, msg, message.Length * sizeof(char), out error);
}
Thank you in advance!
Not quite to the tea.
If you look closely you'll see that:
The client sends a command with the name OnNameis
While the server expects a command named OnNameIs
This pretty much illustrates the dangers of using strings for commands. Use an Enum instead.