I have a problem in my code with receiving data. How to make unity receive data all the time?I only manage to log in with my code.The server sends information at different times. Can't the client see them?The "HandleResponse" function should go to default:.Am I wrongly programmed to receive data?I tried another way to receive data. How to solve the problem so that the client listens all the time or the server does not send something?
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;
public class LogRegSerw : MonoBehaviour
{
public GameObject gameStartPanel;
GameObject gOPlayer;
public InputField loginInputField;
public InputField passwordInputField;
public InputField loginI;
public InputField passwordI;
private TcpClient client;
List<Player> players = new List<Player>();
class Player
{
public string login;
public Vector2 position;
public Player(string login, Vector2 position)
{
this.login = login;
this.position = position;
}
}
void Start()
{
client = new TcpClient();
client.Connect("localhost", 1234);
Debug.Log("Connected to server");
gOPlayer = GameObject.Find("player");
}
private void SendMyPosition()
{
float x = gOPlayer.transform.position.x;
float y = gOPlayer.transform.position.y;
float z = gOPlayer.transform.rotation.eulerAngles.z;
SendDate("player "+ loginI.text +" "+x+" "+y+" "+z);
}
public void Register()
{
string login = loginInputField.text;
string password = passwordInputField.text;
SendDate("register " + login + " " + password);
Debug.Log("Rejestracja");
}
public void Login()
{
string login = loginI.text;
string password = passwordI.text;
SendDate("login " + login + " " + password);
//ReceiveData();
StartCoroutine(ReceiveData());
}
private void SendDate(string message)
{
NetworkStream stream = client.GetStream();
StreamWriter writer = new StreamWriter(stream);
writer.WriteLine(message);
writer.Flush();
}
/*private void ReceiveData()
{
NetworkStream stream = client.GetStream();
byte[] data = new byte[256];
int bytes = stream.Read(data, 0, data.Length);
string response = Encoding.ASCII.GetString(data, 0, bytes);
HandleResponse(response);
}*/
private IEnumerator ReceiveData()
{
NetworkStream stream = client.GetStream();
byte[] data = new byte[256];
int bytes = stream.Read(data, 0, data.Length);
if (bytes > 0)
{
string response = Encoding.ASCII.GetString(data, 0, bytes);
HandleResponse(response);
}
else
{
yield return new WaitForSeconds(0.1f);
StartCoroutine(ReceiveData());
}
}
private void HandleResponse(string response)
{
string[] command = response.Split(' ');
switch (command[0])
{
case "Success":
Debug.Log(command[1]+" "+command[2]+" "+command[3]);
float xx = float.Parse(command[2]);
float yy = float.Parse(command[3]);
LoginSucc(command[1], xx, yy);
break;
case "Invalid":
Debug.Log("Invalid login or password");
break;
case "List":
Debug.Log("Lista...");
break;
default:
Debug.Log("Cos nie tak Linia 75: " + response);
break;
}
}
private void LoginSucc(string name, float x, float y) /////////////////////
{
Vector3 temp = new Vector3(x ,y, 0);
gOPlayer.transform.position += temp;
gOPlayer.GetComponent<PlayerMov>().zalogowany = true ;
gameStartPanel.gameObject.SetActive(false);
}
void Update()
{
if (Input.GetKeyDown("up")|| Input.GetKeyDown("down")|| Input.GetKeyDown("left")|| Input.GetKeyDown("right"))
{
SendMyPosition();
}
}
}
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
Here is part of the scripts of the Client (HoloLens). I use ReceiveMessage() to receive the data sent from the server, but actually I cannot receive anything. SendImage(byte[] image) can send images from the client to the server and works very well. Why? Is there anything wrong with ReceiveMessage()?
After I get the string data (name form python), I want to use the result of ReceiveMessage() to assign a value to an object's text to display on HoloLens.
'''
using System;
#if UNITY_UWP
using System.IO;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
#endif
public class TcpNetworkClientManager
{
public static string Name = "";
#if UNITY_UWP
private Stream stream = null;
private StreamWriter writer = null;
private StreamReader reader = null;
#endif
public TcpNetworkClientManager(string IP, int port)
{
#if UNITY_UWP
Task.Run(async () => {
StreamSocket socket = new StreamSocket();
await socket.ConnectAsync(new HostName(IP),port.ToString());
stream = socket.OutputStream.AsStreamForWrite();
writer = new StreamWriter(stream);
StreamReader reader = new StreamReader(socket.InputStream.AsStreamForRead());
writer = null;
});
#endif
}
public void SendMessage(string data)
{
#if UNITY_UWP
if (writer != null) Task.Run(async () =>
{
await writer.WriteAsync(data);
await writer.FlushAsync();
});
#endif
}
public void SendImage(byte[] image)
{
#if UNITY_UWP
if (stream != null) Task.Run(async () =>
{
await stream.WriteAsync(image, 0, image.Length);
await stream.FlushAsync();
});
#endif
}
public void ReceiveMessage()
{
#if UNITY_UWP
if (reader != null) Task.Run(async () =>
{
try
{
string message = await reader.ReadToEndAsync();
Name = message;
}
catch (Exception) { }
});
#endif
}
}
'''
Here is the script of the GameObject named client. It is the most important part to realize the function in Unity.
'''
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.WSA.WebCam;
using HoloToolkit.Unity.InputModule;
using System;
using System.Linq;
public class Client: MonoBehaviour, IInputClickHandler
{
public string IP;
public int port;
public Text connectButtonText;
public TextMesh debugText;
private PhotoCapture photoCaptureObject = null;
private Texture2D targetTexture = null;
private Resolution cameraResolution;
private TcpNetworkClientManager client = null;
// Use this for initialization
void Start () {
cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
//debugText.text = cameraResolution.width.ToString() + " " + cameraResolution.height.ToString();
targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
// targetTexture = new Texture2D(480, 270);
// InputManager.Instance.PushFallbackInputHandler(gameObject);
InputManager.Instance.AddGlobalListener(gameObject);
}
void Update()
{
if (client!=null)
{
client.ReceiveMessage();
debugText.text = TcpNetworkClientManager.Name;
}
}
void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
photoCaptureObject.Dispose();
photoCaptureObject = null;
}
void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
photoCaptureFrame.UploadImageDataToTexture(targetTexture);
//byte[] texByte = targetTexture.EncodeToJPG();
//byte[] image = new byte[texByte.Length];
//Array.Copy(texByte, image, texByte.Length);
byte[] image = targetTexture.GetRawTextureData();
client.SendImage(image);
photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}
public void OnInputClicked(InputClickedEventData eventData)
{
if (client != null)
{
PhotoCapture.CreateAsync(true, delegate (PhotoCapture captureObject)
{
photoCaptureObject = captureObject;
CameraParameters cameraParameters = new CameraParameters();
cameraParameters.hologramOpacity = 0.9f;
cameraParameters.cameraResolutionWidth = cameraResolution.width;
cameraParameters.cameraResolutionHeight = cameraResolution.height;
cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;
photoCaptureObject.StartPhotoModeAsync(cameraParameters, delegate (PhotoCapture.PhotoCaptureResult result)
{
photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
});
});
}
}
public void ConnectButtonClicked()
{
if(client != null)
{
Debug.Log("Disconnected");
connectButtonText.text = "Connect";
client = null;
}
else
{
Debug.Log("Connected");
client = new TcpNetworkClientManager(IP, port);
connectButtonText.text = "Disconnect";
}
}
}
'''
Here is part of the scripts of the server (PC). I use clientsock.sendall(name.encode()) to send the data of name (Python receives the image from HoloLens and then process the image to get the name of people in the image) from server to client.
'''
def main():
host = "10.24.82.21"
port = 8000
width = 2048
height = 1152
serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversock.bind((host,port))
serversock.listen(10)
print('Waiting for connections...')
clientsock, client_address = serversock.accept()
print("Succeeded in Connection!")
total = 0
buffer_size = 4*width*height
while True:
data = b''
data = clientsock.recv(buffer_size)
print(len(data))
if len(data) == buffer_size:
tmp = np.frombuffer(data, np.uint8, -1)
img = tmp.reshape(height, width, 4)
#img = cv2.resize(img, (480, 270))
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
img = cv2.flip(img, 0)
#cv2.imshow("img", img)
#cv2.waitKey(1000)
#LoadImages(data)
name = FaceRec(img) #recognize the img and return the name
print (name)
clientsock.sendall(name.encode())
print ("this is " + name)
#cv2.imwrite("out.jpg", img)
#cv2.waitKey(3000)
#cv2.destroyAllWindows()
#break
clientsock.close()
'''
It is possible the ReceiveMessage method is invoked before the asynchronous task assinge the, I made some modifications on your code, you can programmatically store this in your project:
public TcpNetworkClientManager(string IP, int port)
{
#if !UNITY_EDITOR
Connect(IP, port);
#endif
}
#if !UNITY_EDITOR
public async void Connect(string IP, int port)
{
try
{
StreamSocket socket = new StreamSocket();
await socket.ConnectAsync(new HostName(IP), port.ToString());
Stream streamOut = socket.OutputStream.AsStreamForWrite();
writer = new StreamWriter(streamOut) { AutoFlush = true };
Stream streamIn = socket.InputStream.AsStreamForRead();
reader = new StreamReader(streamIn);
ReceiveMessage();
}
catch (Exception e)
{
}
}
#endif
I managed to create a TCP client app that streams video to a server app using Unity and Sockets with the great help of Programmer from this answer: https://stackoverflow.com/a/42727918/8713780
Now I need, while streaming the video, to send a simple text message from the server to the client, which triggers the client to send a response message back to the server right away.
The first try is almost always a success but on the second try, the response message to the server causing the video to get stuck, the message itself is corrupted and I get this exception: "System.OverflowException: Number overflow. at <0x00000> "
This is the server script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System;
using UnityEngine.UI;
using System.IO;
public class MySocketsServer : MonoBehaviour {
TcpListener listner;
TcpClient client;
NetworkStream stream;
StreamWriter streamWriter;
StreamReader streamReader;
int port = 8010;
int SEND_RECEIVE_COUNT = 15;
bool getVideo = false;
bool waitingForClient = false;
bool serverConnected = false;
bool clientConnected = false;
private List<TcpClient> clients = new List<TcpClient>();
WaitForEndOfFrame waitEndOfFrame = new WaitForEndOfFrame();
WaitForFixedUpdate waitFixedUpdate = new WaitForFixedUpdate ();
Texture2D tex;
public RawImage serverRawImage;
public GameObject startServerUiBtn;
public GameObject stopServerUiBtn;
public GameObject startStopTrackingUiBtn;
public Text startStopTrackingTxt;
void Start(){
Application.runInBackground = true;
tex = new Texture2D(2, 2, TextureFormat.RGB24, false);
}
public void StartServer () {
listner = new TcpListener(IPAddress.Any, port);
client = new TcpClient ();
listner.Start();
serverConnected = true;
Debug.Log ("Server conected! - IP = " + Network.player.ipAddress);
UIDebugLog.VisableLog ("Server conected! - IP = " + Network.player.ipAddress);
StartCoroutine (WaitForClient());
startServerUiBtn.SetActive (false);
}
public void StopServer(){
stopServerUiBtn.SetActive (false);
startStopTrackingUiBtn.SetActive (false);
serverConnected = false;
getVideo = false;
streamWriter.Close ();
stream.Close ();
client.Close ();
foreach (TcpClient c in clients) {
c.Close ();
}
if (listner != null)
{
listner.Stop();
}
startServerUiBtn.SetActive (true);
serverRawImage.gameObject.SetActive (false);
}
private void OnApplicationQuit()
{
StopServer ();
}
IEnumerator WaitForClient()
{
clientConnected = false;
waitingForClient = true;
stopServerUiBtn.SetActive (true);
// Wait for client to connect in another Thread
Loom.RunAsync(() =>
{
while (waitingForClient)
{
// Wait for client connection
client = listner.AcceptTcpClient();
// We are connected
clients.Add(client);
clientConnected = true;
}
});
//Wait until client has connected
while (!clientConnected)
{
yield return null;
}
stream = client.GetStream ();
streamWriter = new StreamWriter(stream);
streamReader = new StreamReader(stream);
streamWriter.AutoFlush = true;
startStopTrackingUiBtn.SetActive (true);
serverRawImage.gameObject.SetActive (true);
Debug.Log("Client is Connected!");
UIDebugLog.VisableLog("Client is Connected!");
waitingForClient = false;
getVideo = true;
imageReceiver ();
}
int imageSize;
void imageReceiver()
{
Loom.RunAsync(() =>
{
while (getVideo)
{
//Read Image Count
imageSize = readImageByteSize(SEND_RECEIVE_COUNT);
//Read Image Bytes and Display it
readFrameByteArray(imageSize);
}
});
}
byte[] imageBytesCount;
private int readImageByteSize(int size)
{
bool disconnected = false;
try{
imageBytesCount = new byte[size];
var total = 0;
do
{
var read = stream.Read(imageBytesCount, total, size - total);
if (read == 0)
{
disconnected = true;
break;
}
total += read;
} while (total != size);
}catch(Exception e){
Debug.Log ("readImageByteSize() error: " + e);
disconnected = true;
}
if (disconnected)
{
return -1;
}
else
{
return frameByteArrayToByteLength(imageBytesCount);
}
}
//Converts the byte array to the data size and returns the result
int frameByteArrayToByteLength(byte[] frameBytesLength)
{
return BitConverter.ToInt32(frameBytesLength, 0);
}
byte[] imageBytes;
private void readFrameByteArray(int size)
{
try{
bool disconnected = false;
imageBytes = new byte[size];
var total = 0;
do
{
var read = stream.Read(imageBytes, total, size - total);
if (read == 0)
{
disconnected = true;
break;
}
total += read;
} while (total != size);
bool readyToReadAgain = false;
if (!disconnected)
{
//Display Image on the main Thread
Loom.QueueOnMainThread(() =>
{
displayReceivedImage(imageBytes);
readyToReadAgain = true;
});
}
//Wait until old Image is displayed
while (!readyToReadAgain)
{
System.Threading.Thread.Sleep(1);
}
}catch(Exception e){
Debug.Log ("readFrameByteArray() error: " + e);
}
}
void displayReceivedImage(byte[] receivedImageBytes)
{
tex.LoadImage(receivedImageBytes);
serverRawImage.texture = tex;
}
bool waitingForMsgCallback = false;
public void SendMsgToTheClient(){
try{
// Stop recieving video for a moment:
getVideo = false;
// Start listenung to the callback:
waitingForMsgCallback = true;
StartCoroutine (RecieveMsgCallback());
// send the msg:
streamWriter.WriteLine ("msg_from_the_server");
Debug.Log("msg_from_the_server sended");
UIDebugLog.VisableLog("msg_from_the_server sended");
}catch(Exception e){
Debug.Log("SendMsgToTheClient() error: " + e);
}
}
IEnumerator RecieveMsgCallback(){
while (waitingForMsgCallback) {
try{
if (stream.DataAvailable) {
// get the callback msg:
string callbackMsg = streamReader.ReadLine ();
Debug.Log ("Recieved msg Callback: " + callbackMsg);
UIDebugLog.VisableLog ("Recieved msg Callback: " + callbackMsg);
waitingForMsgCallback = false;
// Continue receiving video:
getVideo = true;
imageReceiver ();
}
}catch(Exception e){
Debug.Log("RecieveStartTrackingCallback() error: " + e);
}
yield return waitFixedUpdate;
}
}
}
And the Client script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using System.Text;
using System.Net;
using UnityEngine.UI;
using System;
using System.IO;
public class MySocketsClient : MonoBehaviour {
TcpClient client;
NetworkStream stream;
StreamWriter streamWriter;
StreamReader streamReader;
int port = 8010;
int SEND_RECEIVE_COUNT = 15;
string IP = "127.0.0.1";
bool connected = false;
bool sendingVideo = false;
bool waitingForMsgFromServer = false;
WebCamTexture webCam;
public RawImage clientRawImage;
Texture2D currentTexture;
WaitForEndOfFrame waitEndOfFrame = new WaitForEndOfFrame();
WaitForFixedUpdate waitFixedUpdate = new WaitForFixedUpdate();
public GameObject StartClientUiBtn;
public GameObject StopClientUIBtn;
public InputField ipField;
Rect captureRect;
void Start () {
Application.runInBackground = true;
if (PlayerPrefs.GetString ("server_address") != "") {
IP = PlayerPrefs.GetString ("server_address");
ipField.text = IP;
}
captureRect = new Rect (0, 0, Screen.width, Screen.height);
InitWebCam();
currentTexture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
frameBytesLength = new byte[SEND_RECEIVE_COUNT];
}
public void StartClientBtn(){
if (IP == "") {
Debug.Log ("Please enter an ip address");
return;
}
StartCoroutine (StartClient());
StartClientUiBtn.SetActive (false);
}
IEnumerator StartClient(){
client = new TcpClient();
StopClientUIBtn.SetActive (true);
//Connect to server from another Thread
Loom.RunAsync(() =>
{
Debug.Log("Connecting to server...");
IPAddress ipaddress = IPAddress.Parse(IP);
client.Connect(ipaddress, port);
Debug.Log("Connected!");
connected = true;
});
while (!connected) {
yield return null;
}
stream = client.GetStream();
streamWriter = new StreamWriter(stream);
streamReader = new StreamReader(stream);
streamWriter.AutoFlush = true;
//Start sending video:
sendingVideo = true;
StartCoroutine(senderCOR());
//Start listening to msg from the server:
waitingForMsgFromServer = true;
StartCoroutine(RecieveServerMsg());
}
public void StopClient(){
StopClientUIBtn.SetActive (false);
connected = false;
sendingVideo = false;
streamReader.Close ();
streamWriter.Close ();
stream.Close ();
if (client != null)
{
client.Close();
}
if (webCam != null && webCam.isPlaying)
{
webCam.Stop();
}
StartClientUiBtn.SetActive (true);
}
void OnApplicationQuit()
{
StopClient ();
}
public void OnChangeAddress(){
IP = ipField.text;
PlayerPrefs.SetString ("server_address", IP);
}
void InitWebCam(){
webCam = new WebCamTexture();
webCam.requestedHeight = 10;
webCam.requestedWidth = 10;
clientRawImage.texture = webCam;
webCam.Play();
}
bool readyToGetFrame = false;
byte[] frameBytesLength;
byte[] jpgBytes;
IEnumerator senderCOR()
{
readyToGetFrame = true;
while (sendingVideo)
{
//Wait for End of frame
yield return waitEndOfFrame;
currentTexture.ReadPixels (captureRect , 0, 0);
currentTexture.Apply();
jpgBytes = currentTexture.EncodeToJPG(12);
//Fill total byte length to send. Result is stored in frameBytesLength
byteLengthToFrameByteArray(jpgBytes.Length, frameBytesLength);
readyToGetFrame = false;
try{
Loom.RunAsync(() =>
{
//NetworkStream videoStream = client.GetStream();
//Send total byte count first
stream.Write(frameBytesLength, 0, frameBytesLength.Length);
//Send the image bytes
stream.Write(jpgBytes, 0, jpgBytes.Length);
//Sent. Set readyToGetFrame true
readyToGetFrame = true;
});
}catch(Exception e){
Debug.Log ("senderCOR() error: " + e.Message);
readyToGetFrame = true;
}
//Wait until we are ready to get new frame(Until we are done sending data)
while (!readyToGetFrame)
{
yield return null;
}
}
}
//Converts the data size to byte array and put result to the fullBytes array
void byteLengthToFrameByteArray(int byteLength, byte[] fullBytes)
{
//Clear old data
Array.Clear(fullBytes, 0, fullBytes.Length);
//Convert int to bytes
byte[] bytesToSendCount = BitConverter.GetBytes(byteLength);
//Copy result to fullBytes
bytesToSendCount.CopyTo(fullBytes, 0);
}
IEnumerator RecieveServerMsg(){
while (waitingForMsgFromServer) {
try{
if (stream.DataAvailable) {
// read the msg from the server:
string msg = streamReader.ReadLine ();
UIDebugLog.VisableLog ("ReadStartTrackingMsg: " + msg);
// send a msg callback to the server:
streamWriter.WriteLine ("Callback Message from the client");
UIDebugLog.VisableLog ("callback sended...");
}
}catch(Exception e){
Debug.Log ("ReadStartTrackingMsg() error: " + e.Message);
}
yield return waitFixedUpdate;
yield return waitEndOfFrame;
}
}
}
The final client app should run on Android and the server app should run on PC. I've tested on both and got the same results.
Any advice will be most appreciated
Thanks!
I am currently learning to program a chat room application that uses a server. So far everything works fine if I run the server and multiple instances of the application on a single machine. When I try to run the server on one machine and the actual chat application from another, I get an exception that reads "a connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond (Ipaddress)(port)"
Server side code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Collections;
using System.Text;
using System.Threading;
namespace ChatAppServer
{
class Program
{
public static Hashtable ClientList = new Hashtable();
const int PORT = 321;
string localIp;
static void Main(string[] args)
{
TcpListener sckServer = new TcpListener(PORT);
TcpClient sckClient = default(TcpClient);
int counter = 0;
sckServer.Start();
Console.WriteLine("Chat Server is now Running ....");
counter = 0;
//Parser myParser = new Parser();
while (true)
{
counter = counter + 1;
sckClient = sckServer.AcceptTcpClient();
string clientData = "";
byte[] recieveData = new byte[10025];
NetworkStream netStream = sckClient.GetStream();
netStream.Read(recieveData, 0, (int)sckClient.ReceiveBufferSize);
clientData = System.Text.Encoding.ASCII.GetString(recieveData);
clientData = clientData.Substring(0, clientData.IndexOf("$"));
ClientList.Add(clientData, sckClient);
Broadcast(clientData + " joined the chat", clientData, false);
Console.WriteLine(clientData + " connected to the chat");
handleClient client = new handleClient();
client.ClientStart(sckClient, clientData, ClientList);
}
sckClient.Close();
sckServer.Stop();
Console.WriteLine("exit");
Console.ReadLine();
}
public static void Broadcast(string msg, string userName, bool flag)
{
foreach (DictionaryEntry Item in ClientList)
{
TcpClient sckBroadcast;
sckBroadcast = (TcpClient)Item.Value;
NetworkStream broadcastStream = sckBroadcast.GetStream();
Byte[] broadcastData = null;
if (flag == true)
{
broadcastData = Encoding.ASCII.GetBytes(userName + ": " + msg);
}
else
{
broadcastData = Encoding.ASCII.GetBytes(msg);
}
broadcastStream.Write(broadcastData, 0, broadcastData.Length);
broadcastStream.Flush();
}
}
public class handleClient
{
TcpClient sckClient;
string clId;
Hashtable ClientList;
public void ClientStart(TcpClient inSckClient, string clientId, Hashtable clist) {
this.sckClient = inSckClient;
this.clId = clientId;
this.ClientList = clist;
Thread ctThread = new Thread(runChat);
ctThread.Start();
}
private void runChat() {
int requestCount = 0;
byte[] recieveData = new byte[10025];
string clientData = "";
string rCount = null;
while ((true))
{
try
{
requestCount += 1;
NetworkStream netStream = sckClient.GetStream();
netStream.Read(recieveData, 0, (int)sckClient.ReceiveBufferSize);
clientData = System.Text.Encoding.ASCII.GetString(recieveData);
clientData = clientData.Substring(0, clientData.IndexOf("$"));
Console.WriteLine(clId + " : " + clientData);
rCount = Convert.ToString(requestCount);
Program.Broadcast(clientData, clId, true);
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
}
}
Chat room application code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
//Need for the application
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace ChatApp
{
public partial class Form1 : Form
{
System.Net.Sockets.TcpClient sckClient = new System.Net.Sockets.TcpClient();
NetworkStream svrStream = default(NetworkStream);
string recieveData = null;
public Form1()
{
InitializeComponent();
btnSend.Enabled = false;
}
private void btnConnect_Click(object sender, EventArgs e)
{
recieveData = "Connected to Server";
msg();
int serverPort = Convert.ToInt32(txtServerPort.Text);
sckClient.Connect(txtServerIp.Text, serverPort);
svrStream = sckClient.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(txtUserName.Text + "$");
svrStream.Write(outStream, 0, outStream.Length);
svrStream.Flush();
Thread ctThread = new Thread(MessageCallBack);
btnSend.Enabled = true;
btnConnect.Enabled = false;
txtUserName.Enabled = false;
txtServerIp.Enabled = false;
txtServerPort.Enabled = false;
ctThread.Start();
}
private void MessageCallBack()
{
while(true)
{
svrStream = sckClient.GetStream();
int buffSize = 0;
byte[] inStream = new byte[10025];
buffSize = sckClient.ReceiveBufferSize;
svrStream.Read(inStream, 0, buffSize);
string returnData = System.Text.Encoding.ASCII.GetString(inStream);
recieveData = "" + returnData;
msg();
}
}
//function to display data strings
private void msg()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(msg));
}
else
{
lstMessage.Items.Add(recieveData);
}
}
private void btnSend_Click(object sender, EventArgs e)
{
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(txtMessage.Text + "$");
svrStream.Write(outStream, 0, outStream.Length);
svrStream.Flush();
txtMessage.Text = "";
}
I have two troubles with your code :
Do not use .ReceiveBufferSize value because it's a different value of your byte array length. And you can have an index out of range exception.
You have a problem of concurrency in the server side. More than 1 thread try to access to the ClientList and this collection is not thread-safe.
To resolve this, you can use the lock keyword
private static object _lock = new object();
//...
lock (_lock)
{
ClientList.Add(clientData, sckClient);
}
lock (_lock)
{
Broadcast(clientData + " joined the chat", clientData, false);
}
//...
lock (_lock)
{
Program.Broadcast(clientData, clId, true);
}
As you're a beginner, i would give you some tips.
Try to use the asynchronous network functions (better than raw threads), an example there.
There is a lot of tutorials about safety with severals connections in C# (with some thing else, better, than the lock keyword).
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
tcp/ip client server not working over internet
i spent the last week working on a simple windows form application that' s supposed to send a couple of integer numbers from client to server or from server to client. So far i have only managed to make it work for lanns, any idea about how to make it work on the open internet ?
Here' s the code in case you need it (also call me noob but i can' t get how this site handles code, ... does not do what i thought it did so feel free to edit my post in case i fail2format)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace client_server_penta
{
public class Client
{
#region Fields
private int turno = 1;
private TcpClient[] clients = new TcpClient[1]; //used to remember the active client
private int CoordinateX, CoordinateY; //coordinates, they are used by the application
#endregion
public Client(string address)
{
TcpClient client = new TcpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(address), 3000);
client.Connect(serverEndPoint);
clients[0] = client;
Thread ReadFromServer = new Thread(new ParameterizedThreadStart(this.ReadHandler));
ReadFromServer.Start(client);
}
public void SendData(int a, int b)
{
NetworkStream clientStream = clients[0].GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(a.ToString() + '$' + b.ToString() + '$');
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
public int ReadCoordinateX()
{
return this.CoordinateX;
}
public int ReadCoordinateY()
{
return this.CoordinateY;
}
private void ReadHandler(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] buffer;
int bytesRead;
while (true)
{
buffer = new byte[10];
bytesRead = 0;
try
{
bytesRead = clientStream.Read(buffer, 0, buffer.Length);
}
catch
{
//an uknown error has occurred
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//data received
ASCIIEncoding encoder = new ASCIIEncoding();
OnDataReceived(encoder.GetString(buffer, 0, buffer.Length));
}
tcpClient.Close();
}
private void OnDataReceived(string text)
{
string first_number = "";
string second_number = "";
int index = 0;
while (text[index] != '$')
first_number += text[index++];
index++;
while (text[index] != '$')
second_number += text[index++];
this.CoordinateX = Convert.ToInt32(first_number);
this.CoordinateY = Convert.ToInt32(second_number);
var myForm = Application.OpenForms["Form2"] as Form2;
myForm.Text = "Turno N." + Convert.ToString(this.turno++);
}
}
}
//and here' s the server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace client_server_penta
{
public class Server
{
private Thread listenThread;
private int turno = 1;
private TcpListener tcpListener;
private TcpClient[] clients = new TcpClient[1]; //used to remember the active client
private int CoordinateX, CoordinateY; //coordinates, they are used by the application
public Server(int port)
{
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
public void SendData(int a, int b)
{
NetworkStream clientStream = clients[0].GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(a.ToString()+'$'+b.ToString()+'$');
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
public int ReadCoordinateX()
{
return this.CoordinateX;
}
public int ReadCoordinateY()
{
return this.CoordinateY;
}
private void ListenForClients()
{
this.tcpListener.Start();
TcpClient client = this.tcpListener.AcceptTcpClient();
clients[0] = client;
Thread ReadFromClient = new Thread(new ParameterizedThreadStart(this.ReadHandler));
ReadFromClient.Start(client);
}
private void ReadHandler(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] buffer = new byte[10];
int bytesRead;
while (true)
{
buffer = new byte[10];
bytesRead = 0;
try
{
bytesRead = clientStream.Read(buffer, 0, buffer.Length);
}
catch
{
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//data received
ASCIIEncoding encoder = new ASCIIEncoding();
OnDataReceived(encoder.GetString(buffer, 0, buffer.Length));
}
tcpClient.Close();
}
private void OnDataReceived(string text)
{
string first_number = "";
string second_number = "";
int index = 0;
while (text[index] != '$')
first_number += text[index++];
index++;
while (text[index] != '$')
second_number += text[index++];
this.CoordinateX = Convert.ToInt32(first_number);
this.CoordinateY = Convert.ToInt32(second_number);
var myForm = Application.OpenForms["Form2"] as Form2;
myForm.Text = "Turno N."+Convert.ToString(this.turno++);
}
}
}
Have you opened the 3000 port on your firewall on the two sides ?
Yes of course ^^
If you have routers, don't forget to edit the configurations too.