Can't send large data from Android through TCP socket - c#

I'm trying to send an array of bytes from android (client) to Linux (server), I can send around 17kB but then the socket send an client socket timeout exception. At the server side I'm using netcat with the next command:
nc -l -p 55000 > out.txt
This works ok because I'm capable of sending files from other computer, for this reason I think the problem is at the client side (Android).
I'm using Visual Studio 2015 with Xamarin to compile the project and I tried many methods to send thought socket with the same result, between 15~20kB sended. Of course the permissions on Android to send through internet and other rights are ok.
This is the first mode I tried:
byte[] data = new byte[200000];
TcpClient client = new TcpClient("192.168.0.245", 55000);
client.SendBufferSize = 8192;
NetworkStream ns = client.GetStream();
ns.ReadTimeout = 1000;
ns.WriteTimeout = 1000;
ns.Write(data, 0, data.Length);
ns.Flush();
ns.Close();
client.Close();
With this method only around 17kB are received and the socket is not closed, but the close methods are executed (I tested it with the debugger placing MessageBox to test in release).
Other method I've tested is this:
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("192.168.0.245"), 55000);
System.Net.Sockets.Socket sender = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sender.ExclusiveAddressUse = true;
sender.LingerState = new LingerOption(true, 1);
sender.NoDelay = true;
sender.SendBufferSize = 8192;
sender.ReceiveBufferSize = 8192;
sender.SendTimeout = 1000;
sender.ReceiveTimeout = 1000;
sender.Ttl = 42;
try{
byte[] data = new byte[200000];
sender.Connect(remoteEP);
for (int a = 0; a < data.Length;)
{
int len = (data.Length - a) > 8192 ? 8192 : data.Length - a;
a += sender.Send(data, a, len, SocketFlags.None);
}
}
catch (Exception e)
{
string a = e.ToString();
}
The program send the first 8192 bytes and in the second round an socket timeout exception is trowed. If I try to send all the bytes is one time the program executes the send method the returned bytes are the total length of the array, this mean all bytes are sent to the socket but only received 17kB.
I've tested other methods to do the same thing with the same results in two phones. The android version for compiler I'm using is 4.2. For VS and Xamarin the latest.
Also I tried to download an app from the market to send files throught TCP to see if the problem is in Netcat, firewalls, SO or other and the files was sended ok.... I'm very frustated, I think I'm doing well all the things.
Thanks in advance

Related

c# how to return a string from a client to a server in TCP and UDP

So in my client I am looking for a way to return how many times a background worker was run to a server. Here is the code section for the client:
}
public int searchcount = 1;
public void SL_Click(object sender, EventArgs e)
{
try
{
TcpClient tcpclnt = new TcpClient();
tcpclnt.Connect(RecieveIP.Text, 8001); // use the ipaddress as in the server program
MessageBox.Show("Connected");
Stream stm = tcpclnt.GetStream();
MessageBox.Show("Listening for information......");
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
string atk = Encoding.UTF8.GetString(bb.AsSpan(0, k));
Console.WriteLine($"S Connected to attack server at IPv4 address {RecieveIP.Text} Attack command Received: {atk}. If command is g, attacking google. Y means attacking yahoo. A means attacking aol. Yo meants attacking youtube, and s is attacking spotify");//test
//if you want your check
//this will not work if your incoming data contains white space or other bytes that were converted.
if (atk == "g" || atk.Contains("g"))
MessageBox.Show("Recieved Command " + atk);
if (atk == "g")
{
MessageBox.Show("Google");
search.RunWorkerAsync();
On thought, I do have a string
public int searchcount = 1;
Which the background worker in question adds one to display to the person running the client how many times it was run.
Console.WriteLine("Since start: " + count++.ToString());
Is there a way to return the count++ string to the server via both TCP and UDP? Thanks.
TCP(socket) is a protocol that you can send packages both ways. Udp on the other hand is stateless, you can only send packages from client to server. You cant maintain UDP connections open and keep sending/receiving packages. That said, you can send packages from client to server using UDP if the server dont need to respond your package.
I'm really doing some resume on what tcp/udp protocols are and i really encourage you to read about them on MS official docs before using anything on production.
Here some TCP , UDP and sockets examples and documentation on MS official docs.
Tcp Client/Server
Udp Client/Server
Sockets

Why is Ruby sockets server working with other Ruby sockets client but not a C# sockets client?

So I have two Ruby programs, they are a client and server sockets programs and they work together exchanging messages. But a C# client does not work. I give MCVE, first the ruby client.
#socketClient.rb
#With thanks to https://code.likeagirl.io/socket-programming-in-ruby-f714131336fd
require "socket"
while sum = $stdin.gets.chomp # Read lines from the socket
socket = TCPSocket.open("localhost", 3000)
#puts "Starting the Client..................."
socket.puts sum
while message = socket.gets # Read lines from the socket
puts message.chomp
end
socket.close # Close the socket
end
#puts "Closing the Client..................."
and the server
#simplestSocketServer.rb
#With thanks to https://code.likeagirl.io/socket-programming-in-ruby-f714131336fd
require "socket"
port = 3000
ipAddress = "127.0.0.1"
server = TCPServer.open(ipAddress, port) # Server would listen on port 3000
loop { # Servers run forever
puts "Starting the Server, accepting connections on port " + port.to_s + "..................."
client_connection = server.accept # Establish client connect connection
begin
clientText = client_connection.gets.chomp
puts clientText
resp = "Acknowledged"
client_connection.puts("#{clientText}" + "#{resp}") # Send the answer to the client
client_connection.puts("Closing the connection with #{client_connection}")
rescue Exception => getException
puts "#{getException}"
end
client_connection.close # Disconnect from the client
}
and the C# console program
using System;
using System.Net.Sockets;
using System.Text;
namespace SimplestCSharpRubySocketsClient
{
class Program
{
static void Main(string[] args)
{
try
{
string ipAddress = "127.0.0.1";
Int16 portNumber = 3000;
TcpClient _client; _client = new TcpClient();
_client.Connect(ipAddress, portNumber);
System.Console.WriteLine("we have connected, seemingly ...");
NetworkStream stream;
stream = _client.GetStream();
Byte[] sendBytes = Encoding.UTF8.GetBytes("some text");
System.Console.WriteLine("writing and flushing some bytes ...");
stream.Write(sendBytes, 0, sendBytes.Length);
stream.Flush();
Byte[] recvBytes = new byte[_client.ReceiveBufferSize];
System.Console.WriteLine("_client.ReceiveBufferSize = " + _client.ReceiveBufferSize); // <--- this prints 65536
System.Console.WriteLine("waiting to read bytes ...");
stream.Read(recvBytes, 0, recvBytes.Length); //<--- hangs here
System.Console.WriteLine("comething came back ...");
string result = Encoding.UTF8.GetString(recvBytes);
string result2 = result.Substring(0, result.LastIndexOf("\r\n"));
_client.Close();
_client.Dispose();
_client = null;
}
catch (Exception ex)
{
//TODO figure out a better error handler
throw ex;
}
}
}
}
The C# program connects and writes bytes but when looking to read bytes it just hangs.
And be aware I am running the C# console program in Visual Studio with admin rights. The two ruby programs run in their own separate Windows console windows.
Folding in some feedback, I added another line in the ruby server to output the clientText. And it prints nothing, suggesting the server is not fully receiving the bytes. Is there a termination signal that C# is required to send?
Thanks in advance.
The problem here is that the C# client does not send a newline at the end of the string, like the Ruby version does (socket.puts sends a string with a newline at the end).
If you change your sendBytes array to include a \n in the payload like this:
Byte[] sendBytes = Encoding.UTF8.GetBytes("some text\n");
you will see that it prints comething came back ... on the console.
The newline is required because of the following gets in the Ruby server:
clientText = client_connection.gets.chomp

Irc client Identify protocol "No Ident repsonse"

My client isn't able to connect to the irc server I am trying to connect to. I did some research and it says that I need to listen on port 113 and respond back to the server in a certain format. I am not sure exactly how to do this. When I tried doing it before I got an error message. Here is the code before I tried listening. The irc sends the message to my client "No ident response". Do I need to create an entire different all together that will listen respond on port 113 or can I do it in here?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace ConnectIRC
{
class Program
{
static void Main(string[] args)
{
string ip = "asimov.freenode.net";
string nick = " NICK IKESBOT \r\n";
string join = "JOIN #NetChat\r\n";
int port = 6667;
const int recvBufSize = 8162;
byte[] recvbBuf = new byte[recvBufSize];
//stores the nick
byte[] nickBuf = Encoding.ASCII.GetBytes(nick);
//Stores the room join
byte[] joinBuf = Encoding.ASCII.GetBytes(join);
Socket conn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
conn.Connect(ip, port);
conn.Send(nickBuf, nickBuf.Length, SocketFlags.None);
conn.Send(joinBuf, joinBuf.Length, SocketFlags.None);
for(;;){
byte[] buffer = new byte[3000];
int rec = conn.Receive(buffer, 0, buffer.Length, 0);
Array.Resize(ref buffer, rec);
Console.WriteLine(Encoding.Default.GetString(buffer));
}
}
}
}
Despite #Saruman's answer above, you don't need to create an ident server to connect to most IRC networks (including freenode). You can completely ignore the error about "No ident response". It's an outdated technology which is no longer secure and only ever worked properly on Unix-based multiuser systems.
Your actual issue appears to be that you never finish registering the connection to the IRC server. The specification states that you need to send both USER and NICK messages:
string ip = "asimov.freenode.net";
string nick = "NICK IKESBOT \r\n";
// format is: USER <username> * * :<realname>
string user = "USER IKESBOT * * :IKESBOT\r\n";
string join = "JOIN #NetChat\r\n";
int port = 6667;
const int recvBufSize = 8162;
byte[] recvbBuf = new byte[recvBufSize];
//stores the nick
byte[] nickBuf = Encoding.ASCII.GetBytes(nick);
byte[] userBuf = Encoding.ASCII.GetBytes(user);
//Stores the room join
byte[] joinBuf = Encoding.ASCII.GetBytes(join);
Socket conn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
conn.Connect(ip, port);
conn.Send(nickBuf, nickBuf.Length, SocketFlags.None);
conn.Send(userBuf, userBuf.Length, SocketFlags.None);
conn.Send(joinBuf, joinBuf.Length, SocketFlags.None);
(You've got an extra space before the NICK - this may or may not break things.)
Aside:
You may find it easier to use TcpClient, StreamReader and StreamWriter to access the underlying socket - they wrap it and deal with the buffers for you. You can then read the response line by line directly into a string, and write to the socket by just passing a string. No fiddling around with encoding and buffers.
TcpClient client = new TcpClient("chat.freenode.net", 6667);
StreamReader reader = new StreamReader(client.GetStream());
StreamWriter writer = new StreamWriter(client.GetStream());
string recievedData = reader.ReadLine();
writer.WriteLine("NICK IKESBOT");
writer.Flush();
Yes you will need to create a totally separate port to listen on and respond back to ident requests
More information on ident can be found here

Incomplete data received across network from C# to Arduino

I am trying to send a word over to an Arduino running as a server, from a WPF C# application. Every now and again the complete work is not sent.
C# Code
public void send(String message)
{
TcpClient tcpclnt = new TcpClient();
ConState.Content = "Connecting.....";
try
{
tcpclnt.Connect("192.168.0.177", 23);
ConState.Content = "Connected";
String str = message;
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
stm.Write(ba, 0, ba.Length);
tcpclnt.Close();
}
catch (Exception)
{
ConState.Content = "Not Connected";
return;
}
}
How it is sent to the method:
String mes = "back;";
send(mes);
Arduino code:
if (client.available() > 0) {
// Read the bytes incoming from the client:
char thisChar = client.read();
if (thisChar == ';')
{
//Add a space
Serial.println("");
}
else {
//Print because it's not a space
Serial.write(thisChar);
}
}
The Arduino is using the chat server example. I am sending "back;" and "forward;" across. The results on the serial monitor:
back
forwaback
forward
back
forwaforwar
The problem seems to be with this code:
if (client.available() > 0) {
// read the bytes incoming from the client:
char thisChar = client.read();
...
}
What it does is:
Check if we have received data from the client
Read a single byte from the client buffer
Exit, and go on to do other things
As the OP pointed out, this comes direct from Arduino chat server example. In that example, this working correctly in loop() depends on the alreadyConnected flag being set right after a new connection is made: if it isn't, then the buffer is flushed before any data is read. That's one possible landmine.
Nonetheless, there is no reason to change the if block to be a while loop in the OP's case so, in other words instead of
if (client.available() > 0) {
have
while (client.available() > 0) {
The only reason to have an if statement there is to make sure that you frequently do other processing in loop() if you have clients that send a lot of data: If the reading of client data is done from inside a while this loop will not exit until the there is no more data from the client. Since this doesn't seem to be an issue in the asked-about case, the if to while change makes sense.

udp server respond on the basis of the request received from the udp client

I am making a UDP application in which I am able to receive the messages from udp client and sending a result back to the udp client...but now i want to set the udp server responses on the basis of the request...like for example if udp client send "Hello" message to the server then server reacts accordingly that if the client send "world" then server reacts accordingly that....In short my problem is that i am not able to read out the string which i am receiving at the server site.....this is window form application in c#
for example here is the code:
int recv;
byte[] data = new byte[1024];
IPEndPoint endpoint = new IPEndPoint(IPAddress.Loopback, 1235);
Socket newsocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
newsocket.Bind(endpoint);
MessageBox.Show("waiting for a client..");
IPEndPoint sen = new IPEndPoint(IPAddress.Loopback, 5001);
EndPoint tmp = (EndPoint)sen;
recv = newsocket.ReceiveFrom(data, ref tmp);
MessageBox.Show(" message recieved", tmp.ToString());
MessageBox.Show(Encoding.ASCII.GetString(data, 0, recv));
now i want to read out the string which i am receiving at the "recv" integer by which i could able to set the responses accordingly that..Please tell me How can i do that...
see this
link maybe it can help, your code seams to be rigth, but if it is not working try to change the encoding
to compare the data to string you need first convert it to an string with this line of code
Encoding.ASCII.GetString(data, 0, recv)
use like this
recv = newsocket.ReceiveFrom(data, ref tmp);
string receiver = Encoding.ASCII.GetString(data, 0, recv);
if (receiver == "Hello"){"do something"}

Categories

Resources