Send message from one program to another in Unity - c#

I have two different executable files running on same computer which has Windows OS. Both of them are build in Unity. I want to send message from one to other without using network.
How do you send message from an exe program to another exe program in Unity?
Is this possible with integrated Mono/.net functionality or something else?

You can use Named Pipes which uses shared memory to communicate with another application on the-same machine.
Go to File --> Build Settings... select PC, Mac & Linux Standalone then click on Player Settings.... Now, change Api Compatibility Level to .NET 2.0.
Close and re-open Visual Studio. Now, you can import using System.IO.Pipes; and be able to use NamedPipeServerStream and NamedPipeClientStream.
Below is a very simplified server and client. You must do that in a Thread and should also handle exception.
If you don't want to use Thread, there is also asynchronous parameter (PipeOptions.Asynchronous) that makes it a non blocking operator. It gets complicated from there and you have to look for some examples for that on MS doc.
Simple Server:
//Create Server Instance
NamedPipeServerStream server = new NamedPipeServerStream("MyCOMApp", PipeDirection.InOut, 1);
//Wait for a client to connect
server.WaitForConnection();
//Created stream for reading and writing
StreamString serverStream = new StreamString(server);
//Send Message to Client
serverStream.WriteString("Hello From Server");
//Read from Client
string dataFromClient = serverStream.ReadString();
UnityEngine.Debug.Log("Received from Client: " + dataFromClient);
//Close Connection
server.Close();
Simple Client:
//Create Client Instance
NamedPipeClientStream client = new NamedPipeClientStream(".", "MyCOMApp",
PipeDirection.InOut, PipeOptions.None,
TokenImpersonationLevel.Impersonation);
//Connect to server
client.Connect();
//Created stream for reading and writing
StreamString clientStream = new StreamString(client);
//Read from Server
string dataFromServer = clientStream.ReadString();
UnityEngine.Debug.Log("Received from Server: " + dataFromServer);
//Send Message to Server
clientStream.WriteString("Bye from client");
//Close client
client.Close();
The StreamString class from MS Doc:
public class StreamString
{
private Stream ioStream;
private UnicodeEncoding streamEncoding;
public StreamString(Stream ioStream)
{
this.ioStream = ioStream;
streamEncoding = new UnicodeEncoding();
}
public string ReadString()
{
int len = 0;
len = ioStream.ReadByte() * 256;
len += ioStream.ReadByte();
byte[] inBuffer = new byte[len];
ioStream.Read(inBuffer, 0, len);
return streamEncoding.GetString(inBuffer);
}
public int WriteString(string outString)
{
byte[] outBuffer = streamEncoding.GetBytes(outString);
int len = outBuffer.Length;
if (len > UInt16.MaxValue)
{
len = (int)UInt16.MaxValue;
}
ioStream.WriteByte((byte)(len / 256));
ioStream.WriteByte((byte)(len & 255));
ioStream.Write(outBuffer, 0, len);
ioStream.Flush();
return outBuffer.Length + 2;
}
}

You could have a file they both write and read to.
You can put a timestamp with it to show when the last message was written

Related

Transfer real time live audio From microphone over TCP/IP Using C# .net

I want to make an app to transfer Audio from the microphone in a laptop or PC live, in real time, like a YouTube stream but without video. I will describe my process:
I transfer a normal file by converting it to byte then back again to origin.
I change the file type to MP3 or wav then use NAudio. Works fine also I can play the file if transferred or while receiving
I change the input file to Microphone and receive the audio.
Here is the problem: NAudio is unable to put the live stream from the mic then send it automatically. Always, the buffer gives me a null pointer exception while debugging ,then it gives me another error that the decoder of NAudio did not receive any data, "not acceptable by the way".
It should listen or keep receiving data until the port or connection closes.
I've tried to search about any library about VoIP but found nothing except Ozeki, but no tutorial to handle. All I found is old videos that do not work. I searched about that over a week but no result. I don't want a fully developed project because I already found one, but it is too complex -- about 2K lines of code. All I need is to know what to do or to be given the code that solves the problem.
This is client side code:
public void client()
{
try
{
//byte[] send_data = Audio_to_byte(); // ORIGINAL WORK CODE
byte[] send_data = new byte [BufferSize]; // 100M buffer size
TcpClient client = new TcpClient(serverip, port);
NetworkStream stream = client.GetStream();
// sourceStream and wavein is global vars
sourceStream = new NAudio.Wave.WaveIn();
sourceStream.DeviceNumber = 1;
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(1).Channels);
wavein = new NAudio.Wave.WaveInProvider(sourceStream);
//wavein.Read(send_data, 0, send_data.Length); // this buffer not work some times give me full buffer
BufferedWaveProvider pro = new BufferedWaveProvider(wavein.WaveFormat);
pro.AddSamples(send_data, 0, send_data.Length); // Empty buffer or error full buffer
stream.Write(send_data, 0, send_data.Length);
stream.Close();
client.Close();
}
catch (Exception e)
{
MessageBox.Show("Server is offline" + e, "Error");
// Here the message is buffer is full or send it empty then the decoder did not receive anything give exception error or of them happen first
}
}
and this server side code with MP3 reader code
IPAddress ip = Dns.GetHostEntry(serverip).AddressList[0];
TcpListener server_obj = new TcpListener(ip,port);
TcpClient client = default(TcpClient);
try
{
server_obj.Start();
while (true)
{
// accept all client
client = server_obj.AcceptTcpClient();
// make byte storage from network
byte[] received_buffer = new byte[BufferSize];
//get data from cst
NetworkStream stream = client.GetStream();
//save data from network to memory till finish then save with playing
MemoryStream ms = new MemoryStream();
int numBytesRead = 0;
while ((numBytesRead = stream.Read(received_buffer, 0, received_buffer.Length)) > 0)
{
// THIS STEP TO RECEIVE ALL DATA FROM CLIENT
ms.Write(received_buffer, 0, numBytesRead);
//receive sound then play it direct
WaveOut(ms.ToArray());
}
Byte_to_audio(ms.ToArray()); // YOU can make or allow override
}
}
catch(Exception e)
{
MessageBox.Show("Error Message : " + e, "Error");
}
}
this is Method that read stream receiving data from network
private void WaveOut(byte[] mp3Bytes)
{
// MP3 Format
mp3Stream = new MemoryStream(mp3Bytes);
mp3FileReader = new Mp3FileReader(mp3Stream);
wave32 = new WaveChannel32(mp3FileReader, 0.3f, 3f);
ds = new DirectSoundOut(); // but declration up global
ds.Init(wave32);
ds.Play(); // work code*/
}
I recommend using UDP, if it has to be in real time.
As I use Naudio with vb.net, I based this post.
Client Example:
waveIn = new WaveIn();
waveIn.BufferMilliseconds = 50; //Milissecondes Buffer
waveIn.DeviceNumber = inputDeviceNumber;
waveIn.WaveFormat = HEREWaveFormatHERE;
waveIn.DataAvailable += waveIn_DataAvailable; //Event to receive Buffer
waveIn.StartRecording();
void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
//e -> BUFFER
stream.Write(send_data, 0, send_data.Length);
stream.Close();
client.Close();
}
RECEIVE:
1 - Create WaveOut and BufferProvider Global
WOut = New WaveOut(WaveCallbackInfo.FunctionCallback());
BufferedWaveProvider pro = new BufferedWaveProvider(HEREWaveFormatHERE);
pro.BufferLength = 20 * 1024; //Max Size BufferedWaveProvider
pro.DiscardOnBufferOverflow = True;
WOut.Init(pro);
WOut.Play();
As long as there is no audio BufferedWaveProvider will provide silence for WaveOut or other outputs, it will also queue everything that arrives, for continuous playback.
2 - Play and Enqueue
while ((numBytesRead = stream.Read(received_buffer, 0, received_buffer.Length)) > 0)
{
pro.AddSamples(received_buffer, 0, numBytesRead);
}
My knowledge of naudio is limited to that
English from google translator

Unity .net socket + protobuf issues

Currently I'm trying to develop a multiplayer game with Unity. I checked the Unity's built-in Network and NetworkManager but I need the server dedicated. Hence I developed a java server and implements the protolbuf which is provided by Google. It works with my cocos project but not with this Unity one.
Two problems, first, no matter what did I send to server, the server side has a InvalidProtolBufferException :
While parsing a protocol message, the input ended unexpectedly in the middle > of a field. This could mean either than the input has been truncated or that > embedded message misreported its own length.
second, the stream.read method always makes my unity not responding. Here is my client-side code:
public class SocketClient : MonoBehaviour {
public Text send;
public Text read;
const string ipAddress = "192.168.0.233";
const int port = 8080;
TcpClient socket;
NetworkStream stream;
BinaryWriter bw;
BinaryReader br;
// Use this for initialization
void Start () {
SetupSocket();
}
void SetupSocket() {
socket = new TcpClient(ipAddress, port);
stream = socket.GetStream();
bw = new BinaryWriter(socket.GetStream());
br = new BinaryReader(socket.GetStream());
}
// Update is called once per frame
void Update () {
ReadMessage();
}
public void SendMessage() {
//NetworkStream stream = new NetworkStream(socket.Client);
MessagesProto msg = new MessagesProto();
msg.id = int.Parse(send.text);
using (MemoryStream ms = new MemoryStream())
{
Serializer.Serialize<MessagesProto>(ms, msg);
ms.Position = 0;
byte[] data = ms.ToArray();
ms.Position = 0;
//foreach (byte d in data) {
// Debug.Log(d);
//}
stream.Write(data, 0 , data.Length);
}
}
public void ReadMessage() {
if (stream.CanRead) {
//byte[] receiveData = new byte[socket.ReceiveBufferSize];
byte[] receiveData = new byte[4];
socket.GetStream().Read(receiveData, 0, 4);
Debug.Log("Loading...");
using (MemoryStream ms = new MemoryStream()) {
ms.Write(receiveData, 0, receiveData.Length);
ms.Position = 0;
var msg = Serializer.Deserialize<MessagesProto>(ms);
read.text = msg.data + "";
}
}
}
}
I tried to set the stream.CanRead to stream.DataAvailable, no more crash but not reading anything either, these .Net sockets problems drive me crazy, anyone can help me with this please?
It is not responding because your socket code is synchronous(blocking). You can solve this by either using asynchronous version of the socket functions or use Thread to do all your receiving stuff. This has been answered many times and I will just link to the answers.
TCP Server in Unity
Just port the code to Client.
UDP.

XPS Files Received Through TcpClient are Corrupt

I am trying to create a "virtual printer" application in C# that receives print jobs over the network, parses the raw print data for certain information, and then saves the document into a database. A modified version of the following class is working for postscript print jobs (it saves the incoming data to a valid .prn file, just as though the printer was set to print to the "FILE:" port.) When I try to capture .XPS documents from Microsoft XPS Document Writer, though, the documents cannot be opened. Valid XPS files should also be valid ZIP files if the extension is renamed, and this doesn't work either. When I print the same document to the FILE: port and then to my application, and I compare the results in Notepad++, there is a 5-character difference in the length of the data, but it looks identical (it is not plaintext so it's difficult to look at, but the first few characters and last few characters appear to be the same). The file saved the "normal" way works fine, but the file generated by my code does not.
More generally speaking, I'm trying to receive arbitrary data through a TCP port and write it to a file. My solution is "close" but not working. I don't know what kind of encoding XPS uses, but I am using ASCII for postscript and I have tried ASCII and UTF8 for this XPS version.
Any help is greatly appreciated! Here is the relevant part of my code:
class XPSListener
{
private TcpListener tcpListener;
private Thread listenThread;
private string instanceName = "";
private string fileShare = (Settings.Default.SharedPath.Substring(Settings.Default.SharedPath.Length - 1) == #"\") ? Settings.Default.SharedPath : Settings.Default.SharedPath + #"\"; // use SharedPath setting value - append backslash if it isn't already there.
public XPSListener(string initInstanceName, Int32 initPort)
{
this.instanceName = initInstanceName;
this.tcpListener = new TcpListener(IPAddress.Any, initPort);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
try
{
this.tcpListener.Start();
}
catch (Exception e)
{
MessageBox.Show("Socket Error 1 - " + e.StackTrace);
}
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(AcceptXPSData));
clientThread.Start(client);
}
}
private void AcceptXPSData(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
string tempFilePath = fileShare + "XPStemp_" + instanceName + ".oxps";
byte[] message = new byte[65536];
int bytesRead;
string input;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 65536);
Debug.WriteLine("Bytes read: " + bytesRead.ToString());
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//message has successfully been received
if (instanceName != "DontPrint")
{
Debug.WriteLine(instanceName + " Receiving Data");
//ASCIIEncoding encoder = new ASCIIEncoding();
UTF8Encoding encoder = new UTF8Encoding();
using (FileStream fs = new FileStream(tempFilePath, FileMode.Append, FileAccess.Write))
{
using (StreamWriter sw = new StreamWriter(fs))
{
input = encoder.GetString(message, 0, bytesRead);
sw.Write(input);
// first capture this input and write it to an xps file. This file can be converted to PDF at a later time by Ghostscript
// but we will still have access to the temp file for parsing purposes.
}
}
}
}
tcpClient.Close();
// processXPS();
}
You have at least two problems in your code, one of them almost certainly the reason the file you write is incorrect:
You keep reopening the file you're writing to, rather than just opening it once.
You are interpreting the bytes you receive as text and then re-encoding them.
The first issue is more of an efficiency/file-locking issue than a correctness problem. But the second is a big problem.
As you seem to be aware, an XPS file is basically a .zip file. That means that while the underlying data is XML (i.e. UTF8), the file itself is a compressed binary file. You can't interpret that as text in any meaningful way.
You should simply write the bytes you read straight to the file. A better version of your code would look like this:
private void AcceptXPSData(object client)
{
string tempFilePath = fileShare + "XPStemp_" + instanceName + ".oxps";
using (TcpClient tcpClient = (TcpClient)client)
using (NetworkStream clientStream = tcpClient.GetStream())
using (FileStream fs = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write))
{
clientStream.CopyTo(fs);
}
// processXPS();
}
If you actually want to monitor the I/O as it occurs, you can deal with it explicitly, but still much more simply than your code was:
private void AcceptXPSData(object client)
{
string tempFilePath = fileShare + "XPStemp_" + instanceName + ".oxps";
using (TcpClient tcpClient = (TcpClient)client)
using (NetworkStream clientStream = tcpClient.GetStream())
using (FileStream fs = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write))
{
byte[] message = new byte[65536];
int bytesRead;
while ((bytesRead = clientStream.Read(message, 0, message.Length)) > 0)
{
fs.Write(message, 0, bytesRead);
// Add logging or whatever here
}
}
// processXPS();
}
Note that if you want to handle exceptions, you need to handle only those you specifically expect might happen, and for which you have a reasonable way to deal with. Bare catch clauses, or broad catch (Exception) should be avoided in code like this.

Easy way to send multiple images in a single byte array (via TCP) C#?

Here's the problem: I've successfully setup an app that will pull individual frames of video from a phone and move them to the server. But as you know, the inherent latency won't allow for a smooth transition on the server side. I'm guessing I need to package a number of images in a single byte array and unpack them on the server side. But is there a clean/simple way to do this? Could I use a multi-dimensional array? Something else?
Here's what I got client side (payload is an incoming image converted to a single byte array):
if (_socket != null)
{
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = _socket.RemoteEndPoint;
socketEventArg.UserToken = null;
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
{
response = e.SocketError.ToString();
// Unblock the UI thread
_clientDone.Set();
});
socketEventArg.SetBuffer(payload, 0, payload.Length);
_clientDone.Reset();
_socket.SendAsync(socketEventArg);
_clientDone.WaitOne(TIMEOUT_MILLISECONDS);
}
And here's what I'm doing on the server side:
const int portNo = portNumber;
TcpListener listener = new TcpListener(portNo);
listener.Start();
Console.WriteLine("Listening...");
TcpClient tcpClient = listener.AcceptTcpClient();
NetworkStream NWStream = tcpClient.GetStream();
byte[] bytesToRead = new byte[tcpClient.ReceiveBufferSize + 1];
FrameCount += 1;
int numBytesRead = NWStream.Read(bytesToRead, 0, Convert.ToInt32(tcpClient.ReceiveBufferSize));
string FILE_NAME = "c:\\frames\\" + FrameCount.ToString() + ".gif";
System.IO.FileStream fs = null;
fs = new FileStream(FILE_NAME, FileMode.CreateNew, FileAccess.Write);
fs.Write(bytesToRead, 0, numBytesRead);
fs.Close();
tcpClient.Close();
listener.Stop();
StartImage();
As long as your images are larger than the tcp package size (I think it's 1024 by default on Windows) you won't get performance from sending multiple images in one Send/Receive.
However, sending multiple images per socket connection is useful because you will avoid the overhead of multiple connection handshakes.
Before you optimize your packages, try to send multiple images one after another on the same socket connection.

Reading TCP stream with PHP (converting C# code)

I'm having problems getting/reading any response from a TCP server.
The connection is establishing fine and I'm writing to the server OK but there could be an issue with the particular EOT character required by this server (0x04).
Also the example code I've been given (see below - in C#) converts the string to binary/bytes, which from what I've read PHP doesn't require when using fsockopen & fputs.
My code:
$host = "xxx.xxx.xxx.xxx";
$port = 23432;
$msg = "sample message". chr(4);
$fp = fsockopen ($host, $port, $errno, $errstr);
if (!$fp) {
$lines = "Error: could not open socket connection";
} else {
// write the user string to the socket
fputs ($fp, $msg);
// get the result
$lines .= fgets($fp, 1024);
// close the connection
fclose($fp);
} ?>
Server said: <b><?php echo $lines; ?>
The example C# code I was given:
TcpClient tcp = new TcpClient();
tcp.Connect("xxx.xxx.xxx.xxx", 23432);
Console.WriteLine();
Console.WriteLine("Connected to tcp server.");
// Sent request to tcp server
NetworkStream stream = tcp.GetStream();
// Ask for travel time data
byte[] tx = GetBytes("sample message");
stream.Write(tx, 0, tx.Length);
// Receive data from tcp server
byte[] buffer = new byte[0xffff];
int bytesRead = stream.Read(buffer, 0, 0xffff);
Console.WriteLine("Received " + bytesRead + " bytes from tcp server");
string s = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Below is the data received.");
Console.WriteLine(s);
// Keep the connection open, the data is coming every 20 secs
tcp.Close();
// This function will add the binary byte (0x04) to the end of the text
static private byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length + 1];
Encoding.ASCII.GetBytes(str, 0, str.Length, bytes, 0);
bytes[str.Length] = 0x04;
return bytes;
}
Any ideas? At the moment the PHP code sits there for about 40 seconds after sending the message and returns nothing.

Categories

Resources