I'm trying to stream a video feed form the Xbox Kinect from a client to a server. I got it working with TCP but I could only get about 5 fps so now I'm trying it with UDP. UDP should be faster because of how the protocol works but it seems to be slower. Here is my post about the TCP (http://stackoverflow.com/questions/9627242/c-sharp-streaming-video-over-networkstream-tcpclient)
I can send this all the data I want over my LAN but I start losing a lot of packets if I push them out too fast. That is why I am using the Thread.Sleep(20); Increasing the chuck size speeds it up a lot but I'm at my max for sending over my LAN and if I understand correctly the max chunk size for sending over the internet is about 1500 bytes. If I only sent 1500 bytes at a time this would go really slow. I must be doing something wrong.
Here is the code.
private const int constChunkSize = 38400;
protected UdpClient udpObject;
private void HandleComm()
{
byte[] fullMessage = new byte[1228800];
byte[] byteReceived;
int currentIndex = 0;
IPEndPoint remoteIPEndPoint = new IPEndPoint(ip, port);
while (true)
{
byteReceived = udpObject.Receive(ref remoteIPEndPoint);
if (currentIndex + byteReceived.Length > 1228800)
{
int wtf = 0;
}
Array.Copy(byteReceived, 0, fullMessage, currentIndex, byteReceived.Length);
currentIndex += byteReceived.Length;
//Console.WriteLine("Recieved: " + currentIndex);
if (currentIndex == 1228800)
{
if (OnDataReceived != null)
{
FrameReceivedArgs args = new FrameReceivedArgs();
args.frame = new byte[fullMessage.Length];
fullMessage.CopyTo(args.frame, 0);
OnDataReceived(this, args);
}
currentIndex = 0;
Console.WriteLine("Done receiving" + DateTime.Now.Ticks);
}
}
}
public void sendData(byte[] data)
{
sending = true;
sendThread = new Thread(sendDataThread);
sendThread.Priority = ThreadPriority.Highest;
sendThread.Start(data);
}
private void sendDataThread(object tempData)
{
byte[] data = (byte[]) tempData;
int totalBytes = data.Length;
int currentBytes = 0;
int bufferLength = constChunkSize;
byte[] sendBytes = new byte[constChunkSize];
while (currentBytes < totalBytes)
{
if (totalBytes - currentBytes < constChunkSize)
bufferLength = totalBytes - currentBytes;
Array.Copy(data, currentBytes, sendBytes, 0, bufferLength);
currentBytes += bufferLength;
udpObject.BeginSend(sendBytes, bufferLength, new AsyncCallback(sendingData), udpObject);
Thread.Sleep(20);
//Console.WriteLine("Sent: " + currentBytes);
}
Console.WriteLine("done sending" + DateTime.Now.Ticks);
sending = false;
}
private void sendingData(IAsyncResult ar)
{
udpObject.EndSend(ar);
}
Related
I have a wpf gui that I want to upload files from and send to a C client .
I want to send 3 files and for some reason 1 of them is being sent and written (but it adds 8 nulls in the end and removes 4 of the first letters in the file)
and in the other two when I try to receive the size it says their size is 0
I've been stuck on this problem for a while now and i'm becoming depserate as i'm probably missing a small thing , if any of u could give a hand that'll mean a lot ! I really wanna know whats the problem in my code.
I have the files paths in an array and sending it in main like so
C# Main
IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5555);//switch the port
Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(ipPoint);
listenSocket.Listen(1);
Socket clientSocket = listenSocket.Accept();
for (int i = 0; i < 1; i++)
{
SendFile(clientSocket, filePaths[i]);
}
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
SendFile(C# side)
public static void SendFile(Socket clientSocket, string filePath)
{
if (File.Exists(filePath))
{
FileInfo fi = new FileInfo(filePath);
long file_size = fi.Length;
byte[] preBuffer;
using (var memoryStream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(memoryStream))
{
writer.Write(file_size);
}
preBuffer = memoryStream.ToArray();
byte[] fixedBuffer = new byte[4];
Array.Copy(preBuffer, 0, fixedBuffer, 0, 4);
Console.WriteLine(BitConverter.ToString(preBuffer));
Console.WriteLine(BitConverter.ToString(fixedBuffer)); //fixing the problem i had with the converting to array that it added 4 useless zeros.
clientSocket.Send(fixedBuffer); // sending size
}
byte[] data = new Byte[4096];
using (FileStream fs = new FileStream(filePath, FileMode.Open))
{
int actualRead;
do
{
actualRead = fs.Read(data, 0, data.Length);
clientSocket.Send(data);
file_size -= actualRead;
} while (file_size - filePath.Length > 0);
}
}
else
{
MessageBox.Show("File for the program is missing! lua/pcap/csv");
}
}
C Receive(built from 3 functions)
/*
============================================
General : function is responsible for receiving a length of data from the client
Parameters : sock - client socket to receive the data from
*buf - holds a pointer to the buffer that needs to update
bufsize - the length of the buffer
Return Value : returns TRUE when the data is read correctly
else, FALSE when there was a socket error or no bytes are received.
============================================
*/
bool recv_raw(SOCKET sock, void* buf, int bufsize)
{
unsigned char* pbuf = (unsigned char*)buf;
while (bufsize > 0) {
int num = recv(sock, pbuf, bufsize, 0);
if (num <= 0) { return false; }
pbuf += num;
bufsize -= num;
}
return true;
}
/*
===================================================
General : receives the length of the file and updates it
Parameters : sock - client socket to receive the data from
*filesize - holds a pointer to the size of the buffer that needs to update
filesize_len - the length of the file size pointer
Return Value : returns TRUE when the size is read correctly
else, FALSE when there was a socket error or no bytes are received.
===================================================
*/
bool recv_file_len(SOCKET sock, long* filesize)
{
if (!recv_raw(sock, filesize, sizeof(*filesize))) { return false; }
return true;
}
/*
================================================== =
General : writes to the lua file the data from the file
that was received in the socket
Parameters : sock - the socket between the client and server
*f - the file to write the data received to
Return Value : returns TRUE when everything was written to the file.
returns FALSE if there's no data received or detected a socket problem.
================================================== =
*/
bool write_data(SOCKET sock, FILE *f)
{
long filesize;//size of address
char buffer[BUFFER_SIZE];
if (!recv_file_len(sock, &filesize)) { return false; }
printf("file size (From C#) : %ld\n", filesize);
int n = recv_raw(sock, buffer, 8); // need to get the size of the name
if (filesize > 0)
{
do {
int num = min(filesize, BUFFER_SIZE);
if (!recv_raw(sock, buffer, num)) {
return false;
}
int offset = 0;
do
{
size_t written = fwrite(&buffer[offset], 1, num - offset, f);
if (written < 1) { return false; }
offset += written;
} while (offset < num);
filesize -= num;
} while (filesize > 0);
}
return true;
}
C Main
FILE* luafhandler = fopen("test.lua", "wb");//the new lua file
if (luafhandler == NULL)
{
fclose(luafhandler);
printf("GUI CONNECT lua file failed to open!\n");
}
FILE* pcapfhandler = fopen("test.pcap", "wb");//the new lua file
if (pcapfhandler == NULL)
{
fclose(pcapfhandler);
printf("GUI CONNECT pcap file failed to open!\n");
}
FILE* csvfhandler = fopen("AlgoTest.csv", "wb");//the new lua file
if (csvfhandler == NULL)
{
fclose(csvfhandler);
printf("GUI CONNECT csv file failed to open!\n");
}
else {
SOCKET sock1 = open_socket(5555, SERVER_IP);
bool check = write_data(sock1, luafhandler);
bool check1 = write_data(sock1, pcapfhandler);
bool check2 = write_data(sock1, csvfhandler);
fclose(luafhandler);
fclose(pcapfhandler);
fclose(csvfhandler);
}
I found TCPListener code from here.
In MainWindow class Im starting server.
Then opening websocket from html page
let socket = new WebSocket("ws://192.168.1.149:1112");
Right after this CPU loads to 25% even if nothing sent to server. Further data sending to server going normal. What to do to prevent CPU load? Please help.
class TcpServer
{
public string ip;
public int port;
private Thread bgThread;
public void StartListen()
{
bgThread = new Thread(new ThreadStart(Start))
{
IsBackground = true
};
bgThread.Start();
}
public void Start()
{
TcpListener server = new TcpListener(IPAddress.Parse(ip), port);
server.Start();
TcpClient client = server.AcceptTcpClient();
NetworkStream stream = client.GetStream();
while (true)
{
while (!stream.DataAvailable) ;
while (client.Available < 3) ; // match against "get"
byte[] bytes = new byte[client.Available];
stream.Read(bytes, 0, client.Available);
string strbytes = Encoding.UTF8.GetString(bytes);
if(strbytes.StartsWith("GET"))
{
Console.WriteLine("=====Handshaking from client=====\n{0}", strbytes);
string swk = Regex.Match(strbytes, "Sec-WebSocket-Key: (.*)").Groups[1].Value.Trim();
string swka = swk + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
byte[] swkaSha1 = System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(swka));
string swkaSha1Base64 = Convert.ToBase64String(swkaSha1);
// HTTP/1.1 defines the sequence CR LF as the end-of-line marker
byte[] response = Encoding.UTF8.GetBytes(
"HTTP/1.1 101 Switching Protocols\r\n" +
"Connection: Upgrade\r\n" +
"Upgrade: websocket\r\n" +
"Sec-WebSocket-Accept: " + swkaSha1Base64 + "\r\n\r\n");
stream.Write(response, 0, response.Length);
}
else
{
bool mask = (bytes[1] & 0b10000000) != 0;
int msglen = bytes[1] - 128,
offset = 2;
if (msglen == 126)
{
msglen = BitConverter.ToUInt16(new byte[] { bytes[3], bytes[2] }, 0);
offset = 4;
}
else if (msglen == 127)
{
Console.WriteLine("TODO: msglen == 127, needs qword to store msglen");
}
if (msglen == 0)
Console.WriteLine("msglen == 0");
else if (mask)
{
try
{
byte[] decoded = new byte[msglen];
byte[] masks = new byte[4] { bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3] };
offset += 4;
for (int i = 0; i < msglen; ++i)
decoded[i] = (byte)(bytes[offset + i] ^ masks[i % 4]);
string text = Encoding.UTF8.GetString(decoded);
// other code
}
catch(Exception exc)
{
Console.WriteLine(exc.Message + "\n--------\n" + exc.StackTrace);
}
}
else
Console.WriteLine("mask bit not set");
}
}
}
}
private void startServer()
{
tcpserver = new TcpServer
{
ip = ipbox.Text,
port = 1112
};
tcpserver.StartListen();
}
startServer();
P.S: I have not to say anymore but SO says "It looks like your post is mostly code; please add some more details.". So: some words
I am stuck with this serious problem.
I have async TcpListener. Sometimes there are several connected clients and everything is fine. Sometimes even if there is one person. The server starts usage 50-60% of my CPU.
I think the problem could be in handling of reading exceptions but it's my only tip and I don't know how to test it.
Here is code for server:
class Server
{
private TcpListener server;
public Server(string hostname, int port = 25000)
{
server = new TcpListener(IPAddress.Parse(hostname), port);
}
public void ServerStart()
{
server.Start();
WaitForClientConnect();
}
private async void WaitForClientConnect()
{
TcpClient client = await server.AcceptTcpClientAsync();
Console.WriteLine("The async connection created for: " + ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString());
OnClientConnect(client);
}
private void OnClientConnect(TcpClient client)
{
ClientLowAPI clientReq = new ClientLowAPI(client);
WaitForClientConnect();
}
}
Here is the code for handling a single client:
class ClientLowAPI
{
private TcpClient client;
private NetworkStream stream;
public ClientLowAPI(TcpClient clientConnected)
{
client = clientConnected;
stream = client.GetStream();
WaitForHeader();
}
private async void WaitForHeader()
{
byte[] buffer = new byte[4];
int bytesRead = 0;
while (bytesRead < 4)
{
try
{
bytesRead += await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead);
}
catch
{
stream.Close();
client.Close();
return;
}
}
WaitForData(FourBytesToInt(buffer));
}
private async void WaitForData(int length)
{
byte[] buffer = new byte[length];
int bytesRead = 0;
while (bytesRead < length)
{
try
{
bytesRead += await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead);
}
catch
{
stream.Close();
client.Close();
return;
}
}
ExecuteMessage(buffer);
}
private void ExecuteMessage(byte[] binaryData)
{
// Do something with message
WaitForHeader();
}
public async void SendMessage(byte[] message)
{
byte[] buffer = new byte[message.Length + 4];
byte[] length = IntToFourBytes(message.Length);
length.CopyTo(buffer, 0);
message.CopyTo(buffer, 4);
try
{
await stream.WriteAsync(buffer, 0, buffer.Length);
}
catch
{
stream.Close();
client.Close();
return;
}
}
private int FourBytesToInt(byte[] array)
{
int res = 0;
res += array[0] * 256 * 256 * 256;
res += array[1] * 256 * 256;
res += array[2] * 256;
res += array[3];
return res;
}
private byte[] IntToFourBytes(int intValue)
{
byte[] array = new byte[4];
array[0] = (byte)(intValue >> 24);
array[1] = (byte)(intValue >> 16);
array[2] = (byte)(intValue >> 8);
array[3] = (byte)intValue;
return array;
}
}
The problem was caused by this loop:
while (bytesRead < 4)
{
try
{
bytesRead += await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead);
}
catch
{
stream.Close();
client.Close();
return;
}
}
Normally was connection killed by force and server has raised exception but sometimes the connection was properly closed by client by TcpClient.Close() then the exception was not raised and the stream.ReadAsync method start returns 0 which caused infinty loop with huge CPU usage.
for fast fix i used the following condition:
if (bytesRead == 0)
{
throw new System.IO.IOException();
}
I try to create a simple calculator with client-server diagram in c# using System.Net.Socket. Everything working, but in server side, when I try to convert values receive from client, it's always convert the values to decimal, not integer but I try many time, still not solve.
Example, when client input a=5 and b=5 value, in a server side it's turn to 53 and 53.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace Server_Fix
{
class Program
{
private static int SendVarData(Socket s, byte[] data)
{
int total = 0;
int size = data.Length;
int dataleft = size;
int sent;
byte[] datasize = new byte[4];
datasize = BitConverter.GetBytes(size);
sent = s.Send(datasize);
while (total < size)
{
sent = s.Send(data, total, dataleft, SocketFlags.None);
total += sent;
dataleft -= sent;
}
return total;
}
private static byte[] ReceiveVarData(Socket s)
{
int total = 0;
int recv;
byte[] datasize = new byte[4];
recv = s.Receive(datasize, 0, 4, 0);
int size = BitConverter.ToInt32(datasize,0);
int dataleft = size;
byte[] data = new byte[size];
while (total < size)
{
recv = s.Receive(data, total, dataleft, 0);
if (recv == 0)
{
data = Encoding.ASCII.GetBytes("exit ");
break;
}
total += recv;
dataleft -= recv;
}
return data;
}
public static void Main()
{
byte[] data = new byte[1024];
byte[] data1 = new byte[1024];
byte[] data2 = new byte[1024];
byte[] data3 = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
Socket newsock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
newsock.Bind(ipep);
newsock.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = newsock.Accept();
IPEndPoint newclient = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}",
newclient.Address, newclient.Port);
string welcome = "CALCULATOR CLIENT-SERVER DIAGRAM!";
data = Encoding.ASCII.GetBytes(welcome);
int sent = SendVarData(client, data);
string phepToan;
int result=0;
int a = 0, b = 0;
while(true)
{
sent = SendVarData(client, Encoding.ASCII.GetBytes("Nhap vao so a: "));
data1 = ReceiveVarData(client);
//Console.WriteLine("Client: " + Encoding.ASCII.GetString(data));
sent = SendVarData(client, Encoding.ASCII.GetBytes("Nhap vao so b: "));
data2 = ReceiveVarData(client);
//b = Convert.ToInt32(data2);
sent = SendVarData(client, Encoding.ASCII.GetBytes("Cho biet phep tinh can dung la | + | - | * | / |: "));
data3 = ReceiveVarData(client);
phepToan = Encoding.ASCII.GetString(data3);
//a = Convert.ToString(Encoding.ASCII.GetString(data1));
if (phepToan=="+")
{
foreach (byte byteValue in data1)
{
a = Convert.ToChar(byteValue); //It's always turn to Decimal values
}
foreach (byte byteValue in data2)
{
b = Convert.ToChar(byteValue); //It's always turn to Decimal values
}
result = a + b;
sent = SendVarData(client, Encoding.ASCII.GetBytes("Ket qua phep tinh: "+Convert.ToString(result)));
}
if (phepToan == "-")
{
}
if (phepToan == "*")
{
}
if (phepToan == "/")
{
}
}
Console.WriteLine("Disconnected from {0}", newclient.Address);
client.Close();
newsock.Close();
Console.ReadLine();
}
}
}
================================================================
Code of client side
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace Client_Fix
{
class Program
{
private static int SendVarData(Socket s, byte[] data)
{
int total = 0;
int size = data.Length;
int dataleft = size;
int sent;
byte[] datasize = new byte[4];
datasize = BitConverter.GetBytes(size);
sent = s.Send(datasize);
while (total < size)
{
sent = s.Send(data, total, dataleft, SocketFlags.None);
total += sent;
dataleft -= sent;
}
return total;
}
private static byte[] ReceiveVarData(Socket s)
{
int total = 0;
int recv;
byte[] datasize = new byte[4];
recv = s.Receive(datasize, 0, 4, 0);
int size = BitConverter.ToInt32(datasize,0);
int dataleft = size;
byte[] data = new byte[size];
while (total < size)
{
recv = s.Receive(data, total, dataleft, 0);
if (recv == 0)
{
data = Encoding.ASCII.GetBytes("exit ");
break;
}
total += recv;
dataleft -= recv;
}
return data;
}
public static void Main()
{
byte[] data = new byte[1024];
int sent;
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
try
{
server.Connect(ipep);
}
catch (SocketException e)
{
Console.WriteLine("Unable to connect to server.");
Console.WriteLine(e.ToString());
return;
}
string input;
data = ReceiveVarData(server);
string stringData = Encoding.ASCII.GetString(data);
Console.WriteLine(stringData);
while (true)
{
data = ReceiveVarData(server);
Console.Write("Server: " + Encoding.ASCII.GetString(data));
Console.WriteLine("You: " + input);
sent = SendVarData(server, Encoding.ASCII.GetBytes(input));
data = ReceiveVarData(server);
Console.Write("Server: " + Encoding.ASCII.GetString(data));
input = Console.ReadLine();
//Console.SetCursorPosition(0, Console.CursorTop - 1);
Console.WriteLine("You: " + input);
sent = SendVarData(server, Encoding.ASCII.GetBytes(input));
data = ReceiveVarData(server);
Console.Write("Server: " + Encoding.ASCII.GetString(data));
input = Console.ReadLine();
//Console.SetCursorPosition(0, Console.CursorTop - 1);
Console.WriteLine("You: " + input);
sent = SendVarData(server, Encoding.ASCII.GetBytes(input));
data = ReceiveVarData(server);
Console.WriteLine("Server: " + Encoding.ASCII.GetString(data));
}
Console.WriteLine("Disconnecting from server...");
server.Shutdown(SocketShutdown.Both);
server.Close();
Console.ReadLine();
}
}
}
Let's assume byteValue is 53, the codepoint of the character '5'.
Then
Convert.ToChar(byteValue)
will give 53. That's fine, chars in C# have a numeric value, which is their ordinal in the character table.
One way to solve your problem would be this:
var a = int.Parse(ASCIIEncoding.ASCII.GetString(new byte[] { bytevalue }));
Or, again with some speculation, more likely:
var a = int.Parse(ASCIIEncoding.ASCII.GetString(data1));
Here, the numeric representation of the character digit '5' as it comes over the wire (as 53), will be looked up in the ASCII table, giving "5", and then parsed into the desired integer.
But it does not fix the root problems with the whole code, which would require a more thorough planning of how bits of information are to be encoded, transported, and subsequently decoded in a reliable fashion.
I am working on a software that transfers multiple files between different computers but i am faced with the problem of concurrency. When both threads start sending using Task.Run() the bytes mumble up on the receiving side i.e the data clashes together. I have tried locking every possible part of my code that could cause the error all to no avail. This is part of my code.
//code to transfer asynchronously
public void StartTransferAsync(Socket socket)
{
Task.Factory.StartNew(() =>
{
lock (this)
{
uploader = new Uploader(this, socket);
uploader.Upload();
}
});
}
//code to receive the asynchronous files coming in
public byte[] DownloadData()
{
int total = 0;
int recv = 0;
int size = 0;
int dataleft = 0;
byte[] data;
byte[] dataSize = new byte[4];
recv = socket.Receive(dataSize, 0, 4, 0);
size = BitConverter.ToInt32(dataSize, 0);
Console.WriteLine($"Size received: {size}");
if (size > 100038)
{
Console.WriteLine("Shii here");
}
dataleft = size;
data = new byte[size];
while (total < size)
{
recv = socket.Receive(data, total, dataleft, 0);
total += recv;
dataleft -= recv;
}
return data;
}
Please help i really need this.