I'm sorry but I'm kinda having a confusing problem here...
I was using Unity recently and try to make a simple TCP server that can broadcast through all its clients, also to himself where the server itself is one of the client, like chat room or something.
so I did successfully done so, but the problem is, all the data that received by the client is actually twice of the initially data send from client, below is the example of my code
public void broadcast(string data)
{
print("Broadcast");
byte[] dataByte = Encoding.ASCII.GetBytes(data);
print(ClientList.Count);
for(int x = 0; x<ClientList.Count;x++)
{
ClientList[x].Send(dataByte);
print ("something" +ClientList[x].Send(dataByte));
print ("loop");
}
}
and this is how the client will receive it
private void ReceiveData(IAsyncResult ar)
{
print ("ReceiveData Client");
Socket handler = (Socket)ar.AsyncState;
try
{
int x = handler.EndReceive(ar);
print("Receiving Data...");
print (x);
if (x > 0)
{
StringBuilder sb = new StringBuilder();
sb.Append(Encoding.ASCII.GetString(buffer, 0, x));
string content = sb.ToString();
print("Data Received: " + content);
//string[] data = content.Split(';');
//for (int i = 0; i < data.Length; i++)
//{
this.ProcessData(x, content, handler);
//}
sb.Remove(0, sb.Length);
handler.BeginReceive(buffer, 0, 1024, 0, new AsyncCallback(ReceiveData), handler);
}
else
{
print("Connection Closed...");
}
}
catch (Exception e)
{
print(e.Message);
}
}
I try to send test;this is client
and the result is below
Broadcast
1
something20
ReceiveData Client
loop
Receiving data...
40
Data Received: test;this is client test; this is client"
I don't know what or how this went wrong, any help will be appreciated. Thanks b4
The problem is within these two lines:
ClientList[x].Send(dataByte);
print ("something" +ClientList[x].Send(dataByte));
Notice how you've executed ClientList[x].Send(dataByte) twice? That's why you're getting it 2 times on the receiving end. Just remove one of the two lines and you should be fine.
Related
I am using sockets for TCP-IP connection and I would like to establish simple system send-receive from the client side.
Socket sck;
sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint localEndpt = new IPEndPoint(IPAddress.Parse("123.123.123.1"), 12345);
try
{
sck.Connect(localEndpt);
}
catch
{
Console.Write("Unable to Connect");
}
while (true)
{
Console.WriteLine("Enter Text");
string sendtext = Console.ReadLine();
byte[] Data = Encoding.ASCII.GetBytes(sendtext);
sck.Send(Data);
Console.WriteLine("Data Sent!");
byte[] bytesReceived = new byte[sck.ReceiveBufferSize];
int bytes = 0;
String strReceived = "";
int dataAvailable = 0;
while (dataAvailable == 0 || dataAvailable != sck.Available)
{
dataAvailable = sck.Available;
Thread.Sleep(100); // if no new data after 100ms assume transmission finished
}
if (sck.Available > 0)
{
bytes = sck.Receive(bytesReceived, bytesReceived.Length, 0);
strReceived+=Encoding.ASCII.GetString(bytesReceived, 0, bytes);
}
Console.WriteLine("Received from server: " + strReceived);
}
Console.Read();
The problem is that first requests goes throught but the second does not, because socket is not available anymore (socket "Availabe" attribute value is 0). What am I doing wrong? What would be the easiest way to establish multiple send-recieve requests (in order)?
This code works fine for me
private List<Socket> _clients = new List<Socket>();
private Thread _dataReceiveThread;
private bool _isConnected;
private void DataReceive()
{
while (_isConnected)
{
List<Socket> clients = new List<Socket>(_clients);
foreach (Socket client in clients)
{
try
{
if (!client.Connected) continue;
string txt = "";
while (client.Available > 0)
{
byte[] bytes = new byte[client.ReceiveBufferSize];
int byteRec = client.Receive(bytes);
if (byteRec > 0)
txt += Encoding.UTF8.GetString(bytes, 0, byteRec);
}
if (!string.IsNullOrEmpty(txt))
/* TODO: access the text received with "txt" */
}
catch (Exception e)
{
Exception_Handler(e);
}
}
}
}
Just run this code to get started
_isConnected = true;
_dataReceiveThread = new Thread(DataReceive);
_dataReceiveThread.Start();
Update list box in Cross thread:
This code can be placed in the comment section.
myListBox1.Invoke((Action)(() => { myListBox1.Items.Add(txt) }));
Socket. Available does NOT indicate whether the socket is available, but incoming data is available for reading:
https://msdn.microsoft.com/en-us/library/ee425135.aspx
Your program quits because it checks for a reply (incoming data) immediately after sending a message out. Use a Thread.Sleep before checking for data.
Maybe the message has not even been sent, because Socket.Send just places it in the network interface card's output buffer. When the socket finally sends the message, it will upare the connection state. If it got no reply (on a TCP connection), it will tell you that it is disconnected when you query the state. On UDP it will tell you nothing, because UDP is connectionless.
I am trying to create a client/server application where a server sends commands to clients and clients send result back. The clients send data like this:
5|Hello
5 is the length of the string which is sent because then the server knows howmany characters it should receive before it should do something with that data. I tried to do that with this code:
private static void ReceiveCallback(IAsyncResult AR)
{
try
{
while (!Encoding.ASCII.GetString(_buffer).Contains("|"))
{
}
string[] a = Encoding.ASCII.GetString(_buffer).Split('|');
while (Encoding.ASCII.GetString(_buffer).Length < (Int32.Parse(a[0]) + a[0].Length + 1))
{
}
Socket socket = (Socket)AR.AsyncState;
int received = socket.EndReceive(AR);
byte[] dataBuf = new byte[received];
Array.Copy(_buffer, dataBuf, received);
string text = Encoding.ASCII.GetString(dataBuf);
if (!text.Contains("GET") && !text.Contains("HTTP") && text != null)
{
Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + ":" + text);
}
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
}
catch
{
}
}
but this still does not give me the correct result. Also the CPU goes very high.
Picture of the result:
Can someone explain me why this happens? Thanks!
try to replace Encoding.ASCIIto Encoding.UTF8.
It can fix you issue.
Do note that you must to use the same encoding on both sides (sending and receiving data).
I hope it helps you.
have you tried using TcpClient? it can be way easier and gives you more control.
something like;
//make connection
NetworkStream stream = null;
socket = new TcpClient();
socket.Connect("192.168.12.12", 15879);
if (socket.Connected) {
stream = socket.GetStream();
}
//and than wait for tcp packets.
connectionThread = new Thread(ListenServer);
connectionThread.Start();
private void ListenToServer() {
Byte[] data = new Byte[1024];
String message = String.Empty;
Int32 dataLength = 0;
while (socket.Connected) {
try {
while (stream.DataAvailable) {
dataLength = stream.Read(data, 0, data.Length);
message = System.Text.Encoding.UTF8.GetString(data, 0, dataLength);
//do what ever you need here
Thread.Sleep(1);
}
} catch (Exception ex) {
}
Thread.Sleep(100);
}
moreover %1 cpu load!
I need check status of any computers in my local network. But my code isn't effective, because in there is very long response. I tried threads, that checker runs on background. But i need have a faster check. My program runs as client-server.
On my main program i need write available computers to listbox.
Example:
My main client wants get available computers in local network. Computers have a server runs on port 13000. But, when I want find out available computers, in there is too long response.
Variables
string message = "!";
string temp = "";
public static string list = "";
Checker available computers:
public static void checker()
{
string IP;
int statResp = 0;
for (int i = 1; i < 10; i++)
{
IP = "192.168.0." + i;
string msg = "!";
try
{
Int32 port = 13000;
TcpClient client = new TcpClient(IP, port);
Byte[] data = System.Text.Encoding.ASCII.GetBytes(msg);
msg = "!";
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
data = new Byte[256];
String responseData = String.Empty;
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
if (responseData == " " || responseData == "!")
{
statResp = 1; // response is correct server runs
}
stream.Close();
client.Close();
}
catch (ArgumentNullException)
{
continue; // continue with next iteration
}
catch (SocketException)
{
continue; // continue with next iteration
}
if (statResp == 1)
{
list = IP; // list is variable
}
}
}
TIMER - Checking data in list variable
private void timer2_Tick(object sender, EventArgs e)
{
if (temp != list)
{
listBox1.Items.Add(list);
temp = list;
}
}
If list variable have a same value as in temp variable, old address will not be added to list.
I solved my problem. When I will send UDP broadcast packet to UDP listener (client), sender's IP address will be transmitted to sending new packet to last sender. Original sender (server) will receive new IP address from remote client.
I'm connecting to a server that talks in a JSON protocol. It sends each bit of information as a JSON object. Here are three examples.
{"from":"SERVER","code":"SERVER_OK"}
{"from":"SERVER","code":"CHAT_JOIN","data":{"room":"Lobby"}}
{"from":"SERVER","code":"PING","data":{"time":1405901428001}}
My C# code looks like this.
void Start () {
clientSocket = new TcpClient();
clientSocket.Connect("127.0.0.1", 5000);
serverStream = clientSocket.GetStream();
serverStream.BeginRead(buffer, 0, buffer.Length, ReadComplete, buffer);
}
void ReadComplete (IAsyncResult iar) {
buffer = (byte[])iar.AsyncState;
int bytesAvailable = serverStream.EndRead(iar);
string data = System.Text.Encoding.UTF8.GetString(buffer);
Array.Clear(buffer, 0, 4096);
serverStream.BeginRead(buffer, 0, buffer.Length, ReadComplete, buffer);
Debug.Log(data);
}
My debug log looks like this:
{"from":"SERVER","code":"SERVER_OK"}{"from":"SERVER","code":"CHAT_JOIN","data":{"room":"Lobby"}}
{"from":"SERVER","code":"PING","data":{"time":1405901428001}}
{"from":"SERVER","code":"PING","data":{"time":1405901433001}}
{"from":"SERVER","code":"PING","data":{"time":1405901438004}}
It looks like I can receive more than one JSON object at a time in each ReadComplete. I also assume I could receive a partial JSON object as well. What do I need to do to be able to process a single JSON object at a time? I'm guessing I have to concatenate each received chunk of data to a string and the chop off the front of it each object one at a time. I just have no idea how to go about doing that.
I ended up moving into a Thread and processing the stream one byte at a time looking for the JSON object boundaries. For each on I try to parse it and add it a Queue for the parent thread to process.
So far this seems to work without causing any threading issues with the rest of my application and has been working well with the overall performance for my needs.
// The network thread listening to the server
private void NetworkThread () {
Debug.Log("Connecting to server...");
clientSocket = new TcpClient();
clientSocket.Connect("127.0.0.1", 5000);
stream = clientSocket.GetStream();
int braces = 0;
bool inQ = false;
char lastB = ' ';
while (!stopThread) {
char b = (char)stream.ReadByte();
if (b < 0)
return;
buffer.Append((char)b);
if (b == '"' && lastB != '\\') {
inQ = !inQ;
}
else if (b == '{' && !inQ) {
braces += 1;
}
else if (b == '}' && !inQ) {
braces -= 1;
}
lastB = (char)b;
if (braces == 0) {
try {
JSONNode packet = JSONNode.Parse(buffer.ToString());
buffer = new StringBuilder();
lock (lockQueue) {
packetQueue.Enqueue(packet);
}
} catch (Exception e) {
}
}
}
}
Instat of manually reciving the data use Streamreader and it's .ReadLine() method. It looks like the server sends line for line, so it should not be a problem to read response for response.
I send 2 successive packets from my client to the server who is listening using BeginReceive
The server always receives the first packet but not the other EXCEPT if I run the client in debug mode and slowly send the next packet after the other.
Here's a snippet from my sending function
if (soc.Connected)
{
byte[] byData = new byte[System.Text.Encoding.ASCII.GetByteCount("Hi")];
byData = System.Text.Encoding.ASCII.GetBytes("Hi");
soc.Send(BitConverter.GetBytes(byData.Length));
soc.Send(byData);
}
And here's is my call back function located inside of my server:
private void Recieve(IAsyncResult iar)
{
int j = 0;
Socket server_conn = (Socket)iar.AsyncState;
server_conn.EndReceive(iar);
if (!SocketConnected(server_conn))
{
server_conn.Close();
return;
}
if (g_bmsg.Length != 0)
{
logthis(server_conn.RemoteEndPoint.ToString() + ": " + Encoding.ASCII.GetString(g_bmsg, 0, g_bmsg.Length));
}
//Find out who sent this
foreach (ClientData cls in clientlist)
{
if (server_conn.RemoteEndPoint == cls.clientsock.RemoteEndPoint)
{
j = cls.index;
break;
}
}
server_conn.BeginReceive(g_bmsg, 0, g_bmsg.Length, SocketFlags.None, new AsyncCallback(Recieve), server_conn);
}
When working with TCP/IP sockets (or pretty much any communication layer), you rarely have a guarantee that the entire message you intended to send will come in a single packet.
This means that you should always keep a FIFO buffer of your own, and parse it sequentially.
This is the general idea:
// fifo queue (for background thread parsing, make sure it's thread safe)
private readonly ConcurrentQueue<byte> _commQueue = new ConcurrentQueue<byte>();
In your Receive method, you should simply enqueue the data to the FIFO:
private void Receive(IAsyncResult iar)
{
Socket server_conn = (Socket)iar.AsyncState;
// check how many bytes we actually received
var numBytesReceived = server_conn.EndReceive(iar);
if (!SocketConnected(server_conn))
{
server_conn.Close();
return;
}
// get the received data from the buffer
if (numBytesReceived > 0)
{
for (int i = 0; i < numBytesReceived; i++)
_commQueue.Enqueue(g_bmsg[i]);
// signal the parser to continue parsing
NotifyNewDataReceived();
}
// continue receiving
server_conn.BeginReceive(g_bmsg, 0, g_bmsg.Length, SocketFlags.None, new AsyncCallback(Recieve), server_conn);
}