Basic HttpServer | How to read data from NetworkStream properly - c#

I am trying to make a basic webserver for practice, however i think that i'm not reading from the NetworkStream properly... On the picture bellow you can see that request 2 and 3 do not have 2 newlines \r\n\r\n separating them , which means that i'm reading less data.
Also the requests hang for no obvious reason. I think that I am properly closing the stream and the client, by using networkStream.Close(); and tcpClient.Close();
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace HttpServer
{
class Program
{
static void Main(string[] args)
{
var webserver = new Program();
webserver.Listen(12345);
}
public static void ProcessTcpClientAsync(TcpClient tcpClient)
{
// Get a stream object for reading and writing
NetworkStream networkStream = tcpClient.GetStream();
byte[] buffer = readByteBufferFromNetworkStream(networkStream);
string request = Encoding.UTF8.GetString(buffer);
Console.WriteLine(request);
const string HTTPNewLine = "\r\n";
string html = "<h1>Hello from TestServer</h1>";
string response = "HTTP/1.1 200 OK" + HTTPNewLine;
response += "Server: TestServer 2020" + HTTPNewLine;
response += "Content-Type: text/html; charset=utf-8" + HTTPNewLine;
response += "Content-Length: " + html.Length + HTTPNewLine;
response += HTTPNewLine;
response += html;
response += HTTPNewLine;
byte[] responseBytes = Encoding.UTF8.GetBytes(response);
networkStream.Write(responseBytes);
networkStream.Close();
tcpClient.Close();
}
public void Listen(Int32 port)
{
//Int32 port = 12345;
IPAddress localaddr = IPAddress.Parse("127.0.0.1");
TcpListener tcpListener = new TcpListener(localaddr, port);
tcpListener.Start();
// Enter the listening loop (service/daemon)
while (true)
{
//# Sync Version for debugging
TcpClient tcpClient = tcpListener.AcceptTcpClient();
ProcessTcpClientAsync(tcpClient);
//tcpListener.AcceptTcpClientAsync().ContinueWith((res) => ProcessTcpClientAsync(res.GetAwaiter().GetResult()));
}
}
public static byte[] readByteBufferFromNetworkStream(NetworkStream networkStream)
{
byte[] buffer = new byte[256];
int bytesRead = 0;
while (true)
{
int currentBytesRead = networkStream.Read(buffer, bytesRead, buffer.Length - bytesRead);
bytesRead += currentBytesRead;
// If we've read less data than the size of our buffer -> it means there is no more information, so break.
if (currentBytesRead < buffer.Length) { break; }
// If we've reached the end of our buffer -> check to see if there's any more information, or break.
if (bytesRead == buffer.Length)
{
int nextByte = networkStream.ReadByte();
// End of stream? If so, we're done.
if (nextByte == -1)
{
break;
}
// Otherwise resize the buffer, put in the byte we've just read and continue.
else
{
byte[] newBuffer = new byte[buffer.Length * 2];
Array.Copy(buffer, newBuffer, buffer.Length);
newBuffer[bytesRead] = (byte)nextByte;
buffer = newBuffer;
bytesRead++;
}
}
}
// Buffer is now too big. Shrink it.
byte[] resultBuffer = new byte[bytesRead];
Array.Copy(buffer, resultBuffer, bytesRead);
return resultBuffer;
}
}
}

It's part of the standard for this type of response to seperate the header from the body content.
See https://www.rfc-editor.org/rfc/rfc7230#section-3
All HTTP/1.1 messages consist of a start-line followed by a sequence
of octets in a format similar to the Internet Message Format
[RFC5322]: zero or more header fields (collectively referred to as
the "headers" or the "header section"), an empty line indicating the
end of the header section, and an optional message body.
HTTP-message = start-line
*( header-field CRLF )
CRLF
[ message-body ]
(CRLF above will be treated like \r\n)

Related

TcpListener hanging after reading all bytes

I'm trying to use the TcpListener to listen to some data.
I'm sending this request (from Fiddler):
GET http://localhost:10000/ HTTP/1.1
User-Agent: Fiddler
Host: localhost:10000
The listener is here:
internal static class Program
{
private static void Main(string[] args)
{
const int PORT = 10000;
var ipAddressParts = new byte[] {127, 0, 0, 1};
var ipAddress = new IPAddress(ipAddressParts);
var server = new TcpListener(ipAddress, PORT);
const int BUFFER_SIZE = 256;
Console.WriteLine($"Starting on {ipAddress}:{PORT}.");
server.Start();
while (true)
{
var client = server.AcceptTcpClient();
Console.WriteLine("Client accepted");
var stream = client.GetStream();
var readCount = default(int);
var data = new List<byte[]>();
do
{
var buffer = new byte[BUFFER_SIZE];
readCount = stream.Read(buffer, 0, buffer.Length); // Read hanging here.
Console.WriteLine($"Received {readCount} bytes.");
if (readCount != 0)
{
Console.WriteLine(ASCII.GetString(buffer));
}
data.Add(buffer);
} while (readCount != 0);
var message = ASCII.GetBytes($"{DateTime.Now:D} Hello World!!!");
stream.Write(message, 0, message.Length);
stream.Close();
}
}
}
The listener works as expected and received and prints the message, outputting:
Starting on 127.0.0.1:10000.
Client accepted
Received 62 bytes.
GET / HTTP/1.1
User-Agent: Fiddler
Host: localhost:10000
However, it then hangs on the next read operation in the next loop. I understand that there's no more data to read, so I expected it to return zero for the bytes read and then exit the loop.
The MSDN Documentation implied that this is the correct way to use this.
What condition should I be using to check for the end of the read?
In your do-while loop check, use the DataAvailable attribute instead of your own readCount. Documentation can be found here: https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.networkstream.dataavailable?view=netframework-4.8
This would look something like:
do {
...
} while (stream.DataAvailable);

TCP Socket recieves data wrong in C#

I'm trying to send files from a Socket to another Socket. The sockets are running in two different applications, a client application and a server application. This is happening on the same machine now when testing it. The client first sends to the server when it is ready to receive first info about the file that will be sent to it like filename and file size in bytes in a 2056 bytes message. Then it sends a message each time it is ready to receive a new 2048 buffer of file content.
In short, this is the communication flow for each file:
client -"CLIENT_READY_TO_RECEIVE_FILE_INFO"-------> server
client <-"File name+file size of file coming next"- server
client -"CLIENT_READY_TO_RECEIVE_CONTENT_BUFFER" -> server
client <-"2048 byte buffer of file content"-------- server
...the same flow is repeated until all files are sent to the client.
My problem is that the client receives the file info message wrong, although I have double checked that the server sends it corretly. They both use ASCII encoding. Here is my code:
Client code (receives the files):
private void fetchFilesThreadMethod()
{
String localHostName = Dns.GetHostName();
IPAddress[] localIPs = Dns.GetHostAddresses(localHostName);
IPAddress localIP = localIPs[2];
int port = 1305;
IPEndPoint localEP = new IPEndPoint(localIP,port);
fetchFilesSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
fetchFilesSocket.Bind(localEP);
fetchFilesSocket.Listen(1);
fetchFilesSocket = fetchFilesSocket.Accept();
while (true)
{
byte[] receivedFileInfo = new byte[2056];
byte[] receivedFileCont = new byte[2048];
byte[] comMessage = new byte[100];
byte[] comMessageBytes;
String fileInfoStr = String.Empty;
String fileNameStr = String.Empty; ;
String fileExtStr = String.Empty;
String comMessageStr = String.Empty;
String fileSizeStr = String.Empty;
ulong fileSize = 0;
ulong lastBytesSize = 0;
comMessageStr = "CLIENT_READY_TO_RECEIVE_FILE_INFO";
comMessageBytes = Encoding.ASCII.GetBytes(comMessageStr);
for (int i = 0; i < comMessageBytes.Length; i++)
comMessage[i] = comMessageBytes[i];
Console.WriteLine("Bytes available to be flushed by client: " + fetchFilesSocket.Available);
if (fetchFilesSocket.Available > 0)
{
Console.WriteLine(fetchFilesSocket.Available + " bytes flushed by client.");
byte[] flusher = new byte[fetchFilesSocket.Available];
fetchFilesSocket.Receive(flusher, 0, fetchFilesSocket.Available, SocketFlags.None);
}
fetchFilesSocket.Send(comMessage, 0, 100, SocketFlags.None);
Console.WriteLine("Client sent ready to receive file info.");
fetchFilesSocket.Receive(receivedFileInfo,0,2056, SocketFlags.None);
fileInfoStr = Encoding.ASCII.GetString(receivedFileInfo);
Console.WriteLine("Received file info:" + fileInfoStr);
fileNameStr = fileInfoStr.Split(new String[] { "ENDN" }, StringSplitOptions.None)[0];
Console.WriteLine("Received file name:" + fileNameStr);
fileExtStr = fileNameStr.Split('.').Last();
Console.WriteLine("Received file extension:" + fileExtStr);
fileSizeStr = fileInfoStr.Split(new String[] {"ENDS"},StringSplitOptions.None)[0];
fileSizeStr = fileSizeStr.Split(new String[] {"ENDN"},StringSplitOptions.None).Last();
Console.WriteLine("File size string:" + fileSizeStr);
fileSize = Convert.ToUInt64(fileSizeStr,10);
Console.WriteLine("Received file size:" + fileSize);
lastBytesSize = fileSize % 2048;
ulong byteCount = 0;
bool keepReceiving = true;
ulong buffersReceived = 0;
while (keepReceiving)
{
comMessageStr = "CLIENT_READY_TO_RECEIVE_CONTENT_BUFFER";
comMessageBytes = Encoding.ASCII.GetBytes(comMessageStr);
for (int i = 0; i < comMessageBytes.Length; i++)
comMessage[i] = comMessageBytes[i];
fetchFilesSocket.Send(comMessage, 0, 100, SocketFlags.None);
Console.WriteLine("Console sent ready to receive buffer message.");
if (fileSize - byteCount >= 2048)
{
fetchFilesSocket.Receive(receivedFileCont, 0, 2048, SocketFlags.None);
buffersReceived++;
Console.WriteLine("Buffers received:" + buffersReceived);
byteCount = byteCount + 2048;
}
else
{
fetchFilesSocket.Receive(receivedFileCont, 0, 2048, SocketFlags.None); buffersReceived++;
byteCount = byteCount + 2048;
Console.WriteLine("Buffers received:" + buffersReceived);
keepReceiving = false;
}
Console.WriteLine("Bytes received " + byteCount + "/" + fileSize);
//Console.WriteLine("Received bytes in current file:" + byteCount);
}
Console.WriteLine("File received.");
}
}
Server code (sends the files):
private void fetchThreadMethod(Object commandArgs)
{
if (fetchSocket == null)
{
fetchSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
int port = 1304;
IPEndPoint fetchSocketEP = new IPEndPoint(localIP,port);
fetchSocket.Bind(fetchSocketEP);
}
if (!fetchSocket.Connected)
try
{
fetchSocket.Connect(remoteIP, 1305);
if (fetchSocket.Connected)
Console.WriteLine("Server fetch socket connected.");
}catch(Exception e)
{
Console.WriteLine("Something went wrong when connecting the server fetch socket.");
}
FileCollector fCollector = new FileCollector();
String userName = Environment.GetEnvironmentVariable("USERPROFILE");
String targetDirectory = userName + "\\" + commandArgs;
Console.WriteLine("Path sent to file collector:" + targetDirectory);
fCollector.startFileCollector(targetDirectory);
List<FileNode> collectedFiles = fCollector.getCollectedFiles();
String comMessageStr = String.Empty;
foreach (FileNode fNode in collectedFiles)
{
comMessageStr = String.Empty;
byte[] sentFileInfo = new byte[2056];
byte[] sentFileCont = new byte[2048];
byte[] comMessage = new byte[100];
String fileName = fNode.getFileName();
String formattedFileInfo = fileName;
formattedFileInfo += "ENDN";
ulong fileSize = 0;
FileStream fStream = null;
try
{
fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
FileInfo fInfo = new FileInfo(fileName);
fileSize = (ulong) fInfo.Length;
if (fileSize == 0)
continue;
formattedFileInfo += fileSize.ToString() + "ENDS";
}
catch (Exception e)
{
Console.WriteLine("Could not read from file:" + fileName);
deniedAccessFiles.Add(fileName);
continue;
}
byte[] fileInfoBytes = Encoding.ASCII.GetBytes(formattedFileInfo);
for (int i = 0; i < fileInfoBytes.Length; i++)
sentFileInfo[i] = fileInfoBytes[i];
while (!comMessageStr.Equals("CLIENT_READY_TO_RECEIVE_FILE_INFO"))
{
Console.WriteLine("Server waiting for file info ready message from client.");
fetchSocket.Receive(comMessage,0,100,SocketFlags.None);
comMessageStr = Encoding.ASCII.GetString(comMessage);
comMessageStr = comMessageStr.Substring(0,33);
Console.WriteLine("Received parsed message from client:" + comMessageStr);
}
Console.WriteLine("Server received file info ready message from client.");
comMessageStr = String.Empty;
Console.WriteLine("formattedFileInfo:" + formattedFileInfo);
Console.WriteLine("Sent file info:" + Encoding.ASCII.GetString(sentFileInfo));
fetchSocket.Send(sentFileInfo, 0, 2056, SocketFlags.None);
int readByte = 0;
ulong byteCount = 0;
ulong buffersSent = 0;
while (readByte != -1)
{
if (byteCount == 2048)
{
while (!comMessageStr.Equals("CLIENT_READY_TO_RECEIVE_CONTENT_BUFFER"))
{
Console.WriteLine("Server waiting for ready for buffer message from client.");
fetchSocket.Receive(comMessage, 100, SocketFlags.None);
comMessageStr = Encoding.ASCII.GetString(comMessage);
comMessageStr = comMessageStr.Substring(0,38);
Console.WriteLine("Received parsed message from client 1:" + comMessageStr);
}
Console.WriteLine("Server received ready for buffer message from client.");
fetchSocket.Send(sentFileCont, 0, 2048, SocketFlags.None);
comMessageStr = String.Empty;
buffersSent++;
Console.WriteLine("Buffers sent:" + buffersSent);
byteCount = 0;
}
else
{
readByte = fStream.ReadByte();
if (readByte != -1)
{
sentFileCont[byteCount] = Convert.ToByte(readByte);
byteCount++;
}
}
}
while (!comMessageStr.Equals("CLIENT_READY_TO_RECEIVE_CONTENT_BUFFER"))
{
Console.WriteLine("Server waiting for ready for buffer message from client.");
fetchSocket.Receive(comMessage, 100, SocketFlags.None);
comMessageStr = Encoding.ASCII.GetString(comMessage);
comMessageStr = comMessageStr.Substring(0, 38);
Console.WriteLine("Received parsed message from client 2:" + comMessageStr);
}
Console.WriteLine("Server received ready for buffer message from client.");
fetchSocket.Send(sentFileCont, 0, 2048, SocketFlags.None);
buffersSent++;
Console.WriteLine("Buffers sent:" + buffersSent);
comMessageStr = String.Empty;
}
}
Console outputs:
My recommendation would be to utilise the TCPListener and TCPClient classes provided within System.Net.Sockets they really simplify sending messages over TCP/IP.
Server side you need something like this:
class MyTcpListener
{
public static void Listen()
{
TcpListener server = null;
byte[] bytes = new byte[256];
try
{
// Set the TcpListener on port 13000.
const int port = 13000;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
// Enter the listening loop.
while (true)
{
Console.Write("Waiting for a connection... ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
string data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine($"Received: {data}");
// Process the data sent by the client.
data = data.ToUpper();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
Console.WriteLine($"Sent: {data}");
}
// Shutdown and end connection
client.Close();
}
}
catch (SocketException e)
{
Console.WriteLine($"SocketException: {e}");
}
finally
{
// Stop listening for new clients.
server?.Stop();
}
}
}
Obviously you'll want to adapt it to your program's structure. I took this from here but edited it slightly.
And on your client side you want to use something like this:
class MyTCPClient
{
static void Connect(String server, String message)
{
try
{
// Create a TcpClient.
// Note, for this client to work you need to have a TcpServer
// connected to the same address as specified by the server, port
// combination.
int port = 13000;
TcpClient client = new TcpClient(server, port);
// Translate the passed message into ASCII and store it as a Byte array. Any encoding can be used as long as it's consistent with the server.
byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
// Get a client stream for reading and writing.
// Stream stream = client.GetStream();
NetworkStream stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Console.WriteLine($"Sent: {message}");
// Receive the TcpServer.response. This is all optional and can be removed if you aren't recieving a response.
// Buffer to store the response bytes.
data = new byte[256];
// String to store the response ASCII representation.
// Read the first batch of the TcpServer response bytes.
int bytes = stream.Read(data, 0, data.Length);
string responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {responseData}");
// Close everything.
stream?.Close();
client?.Close();
}
catch (ArgumentNullException e)
{
Console.WriteLine($"ArgumentNullException: {e}");
}
catch (SocketException e)
{
Console.WriteLine($"SocketException: {e}");
}
Console.WriteLine("\n Press Enter to continue...");
Console.Read();
}
}
}
Again, this needs to be adapted to your structure and I took it from here. The response stuff can all be removed if you aren't expecting a response from your server.
These two classes are extremely resilient and abstract away all of the complicated stuff, the size of the data buffers can also be changed to whatever size you need.

Server side not reading message correctly

I'm developing a client-server application, where the client is in Android and the server in C#. Before using C# for the server I used autoIT and it worked fine aside from the fact that I had to send messages of 9 characters or else it would get weird symbols.
Now in C# I'm having the same problem. I tried removing all white space but it always leaves something at the start of the message.
Single word messages like:
"SendClose"
the server reads as
" SendClose" or " SendClose" if i remove the white spaces
Note the leading white space. It's interesting because when I check the string length it says it is only 11 characters so I don't know what is going on; maybe 2 tabs?
Here's my C# code:
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class TcpListenerSample {
static void Main(string[] args) {
try {
// set the TcpListener on port 13000
int port = 80;
IPAddress localAddr = IPAddress.Parse("192.168.1.68");
TcpListener server = new TcpListener(localAddr, port);
// Start listening for client requests
server.Start();
// Buffer for reading data
byte[] bytes = new byte[1024];
string data;
//Enter the listening loop
while (true) {
Console.Write("Waiting for a connection... ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
i = stream.Read(bytes, 0, bytes.Length);
while (i != 0) {
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine(String.Format("Received: {0}", data));
// Process the data sent by the client.
data = data.ToUpper();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
Console.WriteLine(String.Format("Sent: {0}", data));
i = stream.Read(bytes, 0, bytes.Length);
}
// Shutdown and end connection
client.Close();
}
}
catch (SocketException e) {
Console.WriteLine("SocketException: {0}", e);
}
Console.WriteLine("Hit enter to continue...");
Console.Read();
}
}
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine(StripExtended(data));
static string StripExtended(string arg)
{
StringBuilder buffer = new StringBuilder(arg.Length); //Max length
foreach(char ch in arg)
{
UInt16 num = Convert.ToUInt16(ch);//In .NET, chars are UTF-16
//The basic characters have the same code points as ASCII, and the extended characters are bigger
if((num >= 32u) && (num <= 126u)) buffer.Append(ch);
}
return buffer.ToString();
}
}
}

During TCP send breakpoint influences outcome

I have a problem with the Client/Server application i'm writing. It's aim is to send a specific directory's files in the Client and send them to a directory on the Server.
I get the files with a foreach, but when i put a breakpoint at the begin of the foreach and I continue until I send all the files I get all of them in my server as I want, when i delete the breakpoint and re-run my application, my server just receives part of the files, and i don't know why.
I'm unsure but I suppose it's a threading issue, but don't know how to solve it.
Server:
static void Main(string[] args)
{
try
{
TcpListener listen = new TcpListener(3003);
TcpClient client;
int bufferSize = 1024;
NetworkStream netStream = null;
int bytesRead = 0;
int allBytesRead = 0;
// Start listening
listen.Start();
// Accept client
client = listen.AcceptTcpClient();
StreamReader reader = new StreamReader(client.GetStream());
netStream = client.GetStream();
string fileName;
bool endOfSend=false;
do
{
fileName = reader.ReadLine();
// Read length of incoming data
byte[] length = new byte[4];
bytesRead = netStream.Read(length, 0, 4);
int dataLength = BitConverter.ToInt32(length, 0);
// Read the data
int bytesLeft = dataLength;
byte[] data = new byte[dataLength];
while (bytesLeft > 0)
{
int nextPacketSize = (bytesLeft > bufferSize) ? bufferSize : bytesLeft;
bytesRead = netStream.Read(data, allBytesRead, nextPacketSize);
allBytesRead += bytesRead;
bytesLeft -= bytesRead;
}
allBytesRead = 0;
bytesLeft = 0;
bytesRead = 0;
// Save file to desktop
Console.WriteLine("File {0} received.", fileName);
File.WriteAllBytes(#"C:\Users\toto2\Desktop\" + fileName, data);
} while (!endOfSend);
netStream.Close();
client.Close();
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("File Receiving fail." + ex.Message);
}
}
Client:
static void Main(string[] args)
{
try
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
int port = 3003;
TcpClient client = new TcpClient();
//NetworkStream netStream;
// Connect to server
try
{
client.Connect(new IPEndPoint(ipAddress, port));
Console.WriteLine("Connecté.....");
SendFiles(client);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// Clean up
client.Close();
Console.Read();
}
catch (Exception ex)
{
Console.WriteLine("File Sending fail." + ex.Message);
}
}
public static void SendFiles(TcpClient cli) {
NetworkStream netS=cli.GetStream();
int bufferSize = 1024;
string[] files = Directory.GetFiles(#"C:\Users\toto\Mes Images\test");
StreamWriter writer = new StreamWriter(cli.GetStream());
foreach (string item in files)
{
writer.WriteLine(Path.GetFileName(item));
writer.Flush();
// Read bytes from image
byte[] data = File.ReadAllBytes(Path.GetFullPath(item));
// Build the package
byte[] dataLength = BitConverter.GetBytes(data.Length);
byte[] package = new byte[4 + data.Length];
dataLength.CopyTo(package, 0);
data.CopyTo(package, 4);
// Send to server
int bytesSent = 0;
int bytesLeft = package.Length;
while (bytesLeft > 0)
{
int nextPacketSize = (bytesLeft > bufferSize) ? bufferSize : bytesLeft;
netS.Write(package, bytesSent, nextPacketSize);
bytesSent += nextPacketSize;
bytesLeft -= nextPacketSize;
}
}
writer.Close();
netS.Close();
}
Thank to anyone will try to help me.
You may want to implement and acknowledgement from the server to the client that it has recieved 1 file. Then instruct the client to send the next file. As far as I can tell you are just sending all the files at once. The following is a simple implementation of the acknowledgement. You should be able to take the relevant parts of it for your scenario.
//
/* Server Program */
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
public class serv {
public static void Main() {
try {
IPAddress ipAd = IPAddress.Parse("172.21.5.99");
// use local m/c IP address, and
// use the same in the client
/* Initializes the Listener */
TcpListener myList=new TcpListener(ipAd,8001);
/* Start Listeneting at the specified port */
myList.Start();
Console.WriteLine("The server is running at port 8001...");
Console.WriteLine("The local End point is :" +
myList.LocalEndpoint );
Console.WriteLine("Waiting for a connection.....");
Socket s=myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
byte[] b=new byte[100];
int k=s.Receive(b);
Console.WriteLine("Recieved...");
for (int i=0;i<k;i++)
Console.Write(Convert.ToChar(b[i]));
ASCIIEncoding asen=new ASCIIEncoding();
s.Send(asen.GetBytes("The string was recieved by the server."));
Console.WriteLine("\nSent Acknowledgement");
/* clean up */
s.Close();
myList.Stop();
}
catch (Exception e) {
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
---------------------------------------------------------------------------
/* Client Program */
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Sockets;
public class clnt {
public static void Main() {
try {
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("172.21.5.99",8001);
// use the ipaddress as in the server program
Console.WriteLine("Connected");
Console.Write("Enter the string to be transmitted : ");
String str=Console.ReadLine();
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen= new ASCIIEncoding();
byte[] ba=asen.GetBytes(str);
Console.WriteLine("Transmitting.....");
stm.Write(ba,0,ba.Length);
byte[] bb=new byte[100];
int k=stm.Read(bb,0,100);
for (int i=0;i<k;i++)
Console.Write(Convert.ToChar(bb[i]));
tcpclnt.Close();
}
catch (Exception e) {
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
You've got a hybrid binary/text protocol. That can be painful. StreamReader buffers parts of the stream. It takes more than it returns immediately as a string. You can't mix it with other readers.
Throw all of this code away and use a higher-level communication mechanism. For example WCF with MTOM for binary streaming. Or HTTP.
If you are unwilling to to that use BinaryReader ad BinaryWriter. They are reasonably easy to use.
Note, that when you read the length you assume that all 4 bytes will arrive in one read. That assumption is false.

how can i send Full name in TCP service in 2nd time?

When i send data through TCP server to client first time full name retrieved when i again send the another name like book it retrieved as (ook) in C sharp
client side code
sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
while (true)
{
IPEndPoint localEndPoint;
localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.2"), 1);
try
{
sck.Connect(localEndPoint);
}
catch
{
Console.Write("Unable to connect to remote end point!\r\n");
);
}
Console.Write("Enter Text: ");
string text = Console.ReadLine();
byte[] data = Encoding.ASCII.GetBytes(text);
sck.Send(data);
Console.Write("Data Sent!\r\n");
sck.Close();
Console.ReadLine();
Server Side Code
while (true)
{
Socket accepted = sck.Accept();
Buffer = new byte[accepted.SendBufferSize];
int bytesRead = accepted.Receive(Buffer);
byte[] formatted = new byte[bytesRead];
for (int i = 0; i < bytesRead; i++)
{
formatted[i] = Buffer[i];
//Console.WriteLine(Buffer[i] + "\r\n");
}
//string strData = Encoding.ASCII.GetString(Buffer);
string strData = Encoding.ASCII.GetString(formatted);
Console.Write(strData + "\r\n");
accepted.Close();
}
There is something which I don't understand, you use Buffer as a variable but that is a type in C#, I don't know where and how you declare it.
Anyway, I would do it like this:
while (true)
{
Socket accepted = sck.Accept();
byte[] buffer = new byte[1024];
int ret=0;
StringBuilder sb= new StringBuilder();
while ((ret=accepted.Receive(buffer)) > 0)
{
sb.Append(Encoding.ASCII.GetString(buffer, 0, ret));
}
Console.Write(sb.ToString() + "\r\n");
accepted.Close();
}
In order to keep a dialog between both sockets you need something called a protocol, which means you know when you have received the whole data then you reply to the sender. A protocol could be: send a packet which inform what you are going to send, length of the message mainly. Other way is to stop reading when something comes into the message, for example the string "#END#" the return character '\r', etc. If you only want to send one single message and received back a reply message one thing you can do, however, is to shutdown the client part, only the send part Socket.Shutdown(SocketShutdown.Send);, with that, the sender tells the receiver it has sent all data, the receiver receives that signal and then it can send a reply message to the sender.
The client:
sck.Send(data);
Console.Write("Data Sent!\r\n");
// tell the server we have done sending data.
sck.Shutdown(SocketShutdown.Send);
// Now receive from the server
byte[] buffer = new byte[1024];
int ret = 0;
StringBuilder sb = new StringBuilder();
while ((ret = sck.Receive(buffer)) > 0)
{
sb.Append(Encoding.ASCII.GetString(buffer, 0, ret));
}
Console.Write(sb.ToString() + "\r\n");
sck.Close();
The server
while (true)
{
Socket accepted = sck.Accept();
byte[] buffer = new byte[1024];
int ret=0;
StringBuilder sb= new StringBuilder();
while ((ret=accepted.Receive(buffer)) > 0)
{
sb.Append(Encoding.ASCII.GetString(buffer, 0, ret));
}
Console.Write(sb.ToString() + "\r\n");
byte[] reply = Encoding.ASCII.GetBytes("I've got it!");
accepted.Send(reply);
accepted.Close();
}

Categories

Resources