I know TCP can't lose packets because It is streamed, however. I'm trying to send (with nodejs) a stream with 5 "52" packets. Format of it should be (1,52,1,52,1,52,1,52,1,52) where 1 is length of the packet.
I'm receiving the same stream both in C# console App on the same PC what server is.
And on android device with Java app in local network.
C# output is:
"1,52,1,52,1,52,1,52,1,52"
But the java output looks like:
"1,52,1,52,52,1,52,1,52"
Nodejs code:
b = new Buffer(1);
b.writeInt8(1,0);
this.sock.write(b);
this.sock.write(String.fromCharCode(event)); //event == 52
Java code:
while(true)
{
int a = in.read(); //in is an instance of InputStream
if(a!= -1)Log.v(getTag(),""+a);
}
Does anyone have an idea what's the problem?
Thanks in advance
/UPDATE:
socket.bytesWritten returns 10 so it's not on the server side.
Ok. That was my bad. Inside java application I've had a lost connection handler which was reading one byte to check if connection is still alive, it was taking it from the stream.
Related
This is very weird.
When I send data to a TCP server, with a TCP client. It corrupts the data, for some extremely odd, and quite annoying reason.
Here is the server code:
TcpListener lis = new TcpListener(IPAddress.Any, 9380); // it needs to be 9380, crucial
lis.Start();
Socket sk = lis.AcceptSocket();
byte[] pd = new byte[sk.ReceiveBufferSize];
sk.Receive(pd);
// cd is the current directory, filename is the file, ex picture.png,
// that was previously sent to the server with UDP.
File.WriteAllBytes(Path.Combine(cd, filename), pd);
Here is the client code:
// disregard "filename" var, it was previously assigned in earlier code
byte[] p = File.ReadAllBytes(filename)
TcpClient client = new TcpClient();
client.Connect(IPAddress.Parse(getIP()), 9380);
Stream st = client.GetStream();
st.Write(p, 0, p.Length);
What happens is data loss. Extreme, sometimes I would upload a 5KB file, but when the server receives and writes the file I send it, it would turn out crazy like 2 bytes. Or it would be 8KB instead! Applications send through this won't even run, pictures show errors, ect.
I would like to note, however, with this, client -> server fails, on the other hand, server -> client works. Strange.
Btw, in case you are interested this is for sending files... Also, using .NET 4.5. Also, my network is extremely reliable.
Hi I think you have some misconceptions about TCP.
I can see you are setting up a server with a receive buffer of x bytes.
Firstly have you checked to see how many bytes that is? I suspect it is very small something like 1024 or something.
When writing data over TCP the data is split into frames. Each time you receive you will get some of the data sent and it will tell you how much of the data has been received . As I can see from your use case you do not know the size of the data to receive so you will have to build up a protocol between your client and server to communicate this. The simplest of such would be to write a 4 byte integer specifying the size of the data to be received.
The communication would go like this.
Client:
Write 4 bytes (file size)
Write Data bytes
Server:
Read 4 bytes (file size)
While we have yet to receive file size read
the stream and push bytes into memory/file stream
This question already has an answer here:
Why does my client socket not receive what my server socket sends?
(1 answer)
Closed 8 years ago.
I am a beginner when it comes to tcp/ip applications. I'm coding a game and recently I added network multiplayer. I used TcpListener and TcpClient objects from System.Net.Sockets to implement networking. Game works great when I test on localhost or LAN. Later, I tested it over a greater distance: between my pc and my azure VM. Results are shocking. Client received only about 7% of messages sent by server. Server received 84% of messages. I know that TCP/IP doesn't understand what message is because it sends data as a stream. This is what I consider a message:
NetworkStream networkStream = ClientSocket.GetStream();
networkStream.Write(_bytes, 0, _bytes.Length); //_bytes is array of bytes
networkStream.Flush();
My server sends about 20-40 messages per second but 99% of them are 10-15 bytes long. Client sends ~4 messages per second. My machine has access to fast and reliable internet connection. I guess that windows azure data center should have good connection as well. How can I improve network performance of my application ?
EDIT: How client is receiving messages:
NetworkStream serverStream = ClientSocket.GetStream();
byte[] inStream = new byte[10025];
serverStream.Read(inStream, 0, inStream.Length);
I just realized that it might be interpretation error, meaning that data is received but it's somehow misinterpreted. For instace, I also send inside a message number that represents the total count of sent messages. This number is interpreted fine by this 7% of messages received by cleint. However, messages received by server have some strange numbers in them. For example i received message 31,32,33 and then 570425344 then 35 and then 0. So I guess bytes might be offset. I don't know how and why would that happen.
You might not get all data in one chunk.
Use the code
var actualReceivedLength = serverStream.Read(inStream, 0, inStream.Length);
and read actualReceivedLength to know how much you received, call Read again until you have read as much as you expect.
Problem
I have PHP client which sends a image file to a C# socket server. My problem is about 30% of the time the file is partially transferred and stops.
PHP END ->
$file = file_get_contents('a.bmp');
socket_write($socket,$file);
C# END ->
int l= Socket.Receive(buffer, buffer.Length, SocketFlags.None);
//create the file using a file stream
How can I always transfer the full file without intermediate states? And why does it happen?
From the documentation for Socket.Receive:
If you are using a connection-oriented Socket, the Receive method will read as much data as is available, up to the number of bytes specified by the size parameter. If the remote host shuts down the Socket connection with the Shutdown method, and all available data has been received, the Receive method will complete immediately and return zero bytes.
This means you may get less than the total amount. This is just the way sockets work.
So if if you get a partial read, you should call Socket.Receive again. You can use the overload of Socket.Receive to continue reading into the same buffer.
Here is an article that shows how "keep reading" until you get what you want:
Socket Send and Receive
If you don't know how big the data is, you must keep reading until Socket.Receive returns zero.
We are trying to get image uploading working with TinyPic that tracks the progress of the upload. We used HttpWebRequest earlier but since that doesn't support tracking progress, we decided to try low level methods such as TcpClient.
The code when executed gets "stuck" in this line:
int networkBytesRead = networkStream.Read(buffer, 0, buffer.Length);
The code hangs there for more than one minute.
Please have a look at this code for the full class:
http://paste2.org/p/331631
Any input is appreciated.
Thanks,
McoreD from ZScreen
Usually this error is caused when client and server are not synchronized, that is may be the server is listening at the same time when client is sending data. may be you should send an empty line or something else, to give server know that he should send data.HttpWebRequest know about that is why he work so good:) You can try to record traffic by tcp snipper in case of HttpWebRequest and compare it with the traffic of NetworkStream
IS this straightforward? Does any one have any good examples? All my google searches return items on how to make telnet clients in dotNet but this overkill for me. I'm trying to do this in C#.
Thanks!
C# 2.0 and Telnet - Not As Painful As It Sounds
http://geekswithblogs.net/bigpapa/archive/2007/10/08/C-2.0-and-Telnet---Not-As-Painful-As-It.aspx
Or this alternative link.
If you're going to use the System.Net.Sockets class, here's what you do:
Create an IPEndpoint, which points to the specified server and port.
You can query DNS.GetHostEntry to change a computer name to an
IPHostEntry object.
Create a socket object with the following
parameters: AddressFamily.InterNetwork (IP version 4),
SocketType.Stream (rides on InterNetwork and Tcp parameters),
ProtocolType.Tcp (reliable, two-way connection)
Open the socket like
this: socket.Connect(endpoint); //yup, it's that simple Send your
data using socket.Send(... wait, I forgot something. You have to
encode the data first so it can fly across them wires.
Use
Encoding.ASCII.GetBytes to convert the nice message you have for the
server into bytes. Then use socket.Send to send those bytes on their
way.
Listen for a response (one byte at a time, or into a byte array)
using socket.Receive Don't forget to clean up by calling
socket.Close()
You can [also] use a System.Net.Sockets.TcpClient object instead of a
socket object, which already has the socket parameters configured to
use ProtocolType.Tcp. So let's walk through that option:
Create a new TcpClient object, which takes a server name and a port (no IPEndPoint necessary, nice).
Pull a NetworkStream out of the TcpClient by calling GetStream()
Convert your message into bytes using Encoding.ASCII.GetBytes(string)
Now you can send and receive data using the stream.Write and stream.Read methods, respectively. The stream.Read method returns the number of bytes written to your receiving array, by the way.
Put the data back into human-readable format using Encoding.ASCII.GetString(byte array).
Clean up your mess before the network admins get mad by calling stream.Close() and client.Close().
For simple tasks (such as connecting to a specialized hardware device with telnet-like interface) connecting via socket and just sending and receiving text commands might be enough.
If you want to connect to real telnet server you might need to handle telnet escape sequences, face terminal emulation, handle interactive commands etc. Using some already tested code such as Minimalistic Telnet library from CodeProject (free) or some commercial Telnet/Terminal Emulator library (such as our Rebex Telnet) might save you some time.
Following code (taken from this url) shows how to use it:
// create the client
Telnet client = new Telnet("servername");
// start the Shell to send commands and read responses
Shell shell = client.StartShell();
// set the prompt of the remote server's shell first
shell.Prompt = "servername# ";
// read a welcome message
string welcome = shell.ReadAll();
// display welcome message
Console.WriteLine(welcome);
// send the 'df' command
shell.SendCommand("df");
// read all response, effectively waiting for the command to end
string response = shell.ReadAll();
// display the output
Console.WriteLine("Disk usage info:");
Console.WriteLine(response);
// close the shell
shell.Close();