Simple way to send strings and files via TCPIP - c#

I want to make a simple client-server application. The server waits for connection from clients. The client can send various queries (short strings of less than 100 char) to the server and the server should respond to these queries by sending strings or files.
I found code online that uses a tcpListener.AcceptSocket() and I can send and receive strings from server and code that uses tcpListener.AcceptTcpClient() and I can send files to a different server program.
Below there is a function for sending files via TcpIP and one for sending strings via TcpIP. How should the server code look like, to acommodate both functions? The server is a console program.
public void SendFileViaTCP(string sFile, string sIPAddress, int portNo)
{
byte[] sendingBuffer = null;
TcpClient client = null;
toolStripStatusLabel1.Text = "";
lbConnect.Items.Clear();
progressBar1.Value = 0;
Application.DoEvents();
NetworkStream networkStream = null;
int bufferSize = 5000;
string checksum = CalculateMD5(sFile);
lbConnect.Items.Add("File " + sFile + " checksum = " + checksum);
try
{
client = new TcpClient(sIPAddress, portNo);
toolStripStatusLabel1.Text = "Connected to the Server...\n";
networkStream = client.GetStream();
FileStream fileStream = new FileStream(sFile, FileMode.Open, FileAccess.Read);
long fsLength = fileStream.Length;
int nPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(fsLength) / Convert.ToDouble(bufferSize)));
progressBar1.Maximum = nPackets;
Application.DoEvents();
int currentPacketLength;
for (int i = 0; i < nPackets; i++) {
if (fsLength > bufferSize) {
currentPacketLength = bufferSize;
fsLength -= currentPacketLength;
Application.DoEvents();
}
else {
currentPacketLength = Convert.ToInt32(fsLength);
}
sendingBuffer = new byte[currentPacketLength];
fileStream.Read(sendingBuffer, 0, currentPacketLength);
networkStream.Write(sendingBuffer, 0, (int)sendingBuffer.Length);
progressBar1.PerformStep();
Application.DoEvents();
}
toolStripStatusLabel1.Text = "Sent " + fileStream.Length.ToString() + " bytes to the server";
fileStream.Close();
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
finally {
networkStream.Close();
client.Close();
}
}
void SendString(string str, string sIPAddress, int portNo)
{
try {
TcpClient tcpClient = new TcpClient();
lbConnect.Items.Add("Connecting...");
Application.DoEvents();
// use the ipaddress as in the server program
var tsk = tcpClient.ConnectAsync(sIPAddress, portNo);
tsk.Wait(3000); // here we set how long we want to wait before deciding the server is not responding.
lbConnect.Items.Add("Connected");
lbConnect.Items.Add("Sending string: " + str);
Application.DoEvents();
Stream stream = tcpClient.GetStream();
ASCIIEncoding asen= new ASCIIEncoding();
byte[] ba=asen.GetBytes(str);
lbConnect.Items.Add("Transmitting...");
Application.DoEvents();
stream.Write(ba,0,ba.Length);
byte[] bb=new byte[100];
int k = stream.Read(bb,0,100);
string sResponse = string.Empty;
for (int i = 0; i < k; i++) {
sResponse += Convert.ToChar(bb[i]);
}
lbConnect.Items.Add(sResponse);
Application.DoEvents();
tcpClient.Close();
}
catch (Exception e) {
lbConnect.Items.Add("Error: " + e.StackTrace);
Application.DoEvents();
}
}

Related

C# Reading stream from TcpClient

I'm making a server - client program using TcpClient and server.
To send from the server I use:
static void send(string data)
{
sw.WriteLine(data + Environment.NewLine);
}
And when the client connects I'm sending some text:
client = listener.AcceptTcpClient();
sr = new StreamReader(client.GetStream());
sw = new StreamWriter(client.GetStream());
string line;
try
{
send("Hello world");
} //More code
And to read from client:
string data;
data = sr.ReadLine();
if(data != string.Empty || data != null)
{
MessageBox.Show(data);
}
I tried putting inside while(true) and it froze, I tried putting inside a timer tick loop and it froze...
How do I fix this?
P.S: The client and the server are 2 different projects.
I believe you need something like this:
try
{
listen = new TcpListener(myAddress, port);
listen.Start();
Byte[] bytes;
while (true)
{
TcpClient client = listen.AcceptTcpClient();
NetworkStream ns = client.GetStream();
if(client.ReceiveBufferSize > 0){
bytes = new byte[client.ReceiveBufferSize];
ns.Read(bytes, 0, client.ReceiveBufferSize);
string msg = Encoding.ASCII.GetString(bytes); //the message incoming
MessageBox.Show(msg);
}
}
}
catch(Exception e)
{
//e
}
Then have this code as a background thread:
Thread thread = new Thread(the functions name);
thread.IsBackground = true;
thread.Start();
I hope I understand what you need.
Try this one, grandpa's way.
int i = 0;
while (stream.DataAvailable == true)
{
bytes[i] = ((byte)stream.ReadByte());
i++;
}
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);

C# and NetworkStream, sending is ok but receiving is not working

here is the source code, I can't understand what happens. When I receive data from server then writes back to the NetworkStream then it works but when I try to send first before reading from the server it does not work :
void BtnConnectClick(object sender, EventArgs e)
{
TcpClient clientSocket = null;
NetworkStream networkStream = null;
try{
clientSocket = new TcpClient();
clientSocket.SendTimeout = 5000;
clientSocket.ReceiveTimeout = 5000;
clientSocket.Connect("192.168.0.13",7777);
networkStream = clientSocket.GetStream();
const string strToAndroid = "hi from client";
char[] carray = strToAndroid.ToCharArray();
for (int i=0;i<carray.GetLength(0);i++)
{
networkStream.WriteByte((byte)carray[i]);
}
log("sent to Android = " + strToAndroid);
string strFromAndroid = "";
int j=0;
while (j!=-1)
{
try
{
j = networkStream.ReadByte();
if (j!=-1)
strFromAndroid += (char)j;
}
catch(Exception ex){
break;
}
}
log("received from Android = " + strFromAndroid);
networkStream.Close();
clientSocket.Close();
}
catch(Exception ex){
log("002:" + ex.Message);
if (networkStream != null)
networkStream.Close();
if (clientSocket != null)
clientSocket.Close();
}
}
This was a server side issue so this code is ok.
The server was never receiving the value -1 so it did not reply back.

Socket communication output issue

In getting used to Sockets using Client server communication here is my code.
//server partl
try
{
IPAddress ipAd = IPAddress.Parse("127.0.0.1"); //use local m/c IP address, and use the same in the client
/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, 8020);
/* Start Listeneting at the specified port */
myList.Start();
Socket s = myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
byte[] b = new byte[100];
int k = s.Receive(b);
//Console.WriteLine("Recieved...");
//Writes to label1
for (int i = 0; i < k; i++)
label1.Text = b[i].ToString();
//ASCII endoing to use ACK.
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 ex)
{
Console.WriteLine("Error..... " + ex.StackTrace);
}
//Client part
try
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("127.0.0.1", 8020); // use the ipaddress as in the server program
Console.WriteLine("Connected");
Console.Write("Enter the string to be transmitted : ");
//gets the text from textbox
String str = textBox1.Text;
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 ex)
{
Console.WriteLine("Error..... " + ex.StackTrace);
}
}
I am using a form to communicate on local host and writing a one .cs file and want to show the text(from textbox) from Client-labelled portion to the label on server-labelled portion.
Any idea why its not showing output?. New to sockets !!!
When socket receives the data instead of loop simply use this:
if (k > 0)
label1.Text = Encoding.UTF8.GetString(b);
Also you can use this for simply send and receive data using TcpClient which is a wrapper around socket.

Force code execution till the end of method

I'm working on client-server multithreading application:
Progress of communication is:
Server listens on socket
Client connects and send request or requests to server
Each request is ended by 0x04
Server must proceess each request with operation which is slower than incoming requests
I have a problem in "ProcessClient" method when two requests occur in short time and first request cannot be processed till the end of method beacuse second request is coming to process. Problem occurs after foreach loop:
foreach (var t in invoices)
{
SaveToDataBase(t);
}
Method does not executes till the end and it does not sends response to client with following code snippet:
var ResponseFile = ResponseClientFolder + "\\" + ResponseClientFileName + x + ".txt";
StreamWriter sw = File.CreateText(ResponseFile);
sw.WriteLine(_odgovor);
sw.Close();
_odgovor = string.Empty;
SendToClient(ResponseFile);
beacuse second request occurs at "ProcessClient" method.
Is there any way to solve this problem. I was looking for many solution without success.
Whole code is below:
private void RunListener()
{
try
{
_listener = new TcpListener(IPAddress.Parse(ServerAddres), ServerPort);
_listener.Start();
while (true)
{
TcpClient client = _listener.AcceptTcpClient();
Invoke(new Action(() => { }));
ThreadPool.QueueUserWorkItem(ProcessClient, client);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, #"Run listener");
}
}
private void ProcessClient(object state)
{
try
{
byte[] bytes = new byte[1024];
TcpClient client = state as TcpClient;
StringBuilder completeMessage = new StringBuilder();
if (client == null) return;
networkStream = client.GetStream();
int bytesRead = 0;
do
{
bytesRead = networkStream.Read(bytes, 0, bytes.Length);
completeMessage.AppendFormat("{0}", Encoding.Default.GetString(bytes, 0, bytesRead));
} while (bytesRead > 0 && bytes[bytesRead - 1] != 0x04);
completeMessage = completeMessage.Replace(#"”", "");
string datetime = DateTime.Now.ToString();
var x = datetime.Replace(".", string.Empty).Replace(":", string.Empty).Replace(" ", string.Empty);
var inputfilename = "Racun" + x + ".txt";
StreamWriter sws = File.CreateText(inputfilename);
sws.WriteLine(completeMessage);
sws.Close();
string data = completeMessage.ToString();
char[] delimiters = { '\r', '\n' };
string[] invoices = data.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
foreach (var t in invoices)
{
SaveToDataBase(t);
}
var ResponseFile = ResponseClientFolder + "\\" + ResponseClientFileName + x + ".txt";
StreamWriter sw = File.CreateText(ResponseFile);
sw.WriteLine(_odgovor);
sw.Close();
_odgovor = string.Empty;
SendToClient(ResponseFile);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, #"Proces client");
}
}
private void SendToClient(string ResponseFile)
{
try
{
byte[] byteData = File.ReadAllBytes(ResponseFile);
List<byte> byteDat = new List<byte>();
byteDat.AddRange(byteData);
byteDat.Add(0x04);
byteData = byteDat.ToArray();
networkStream.Write(byteData, 0, byteData.Length);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, #"Send to client");
}
}

Help with Exception with TCPListener

I keep getting the following exception when a client connects to the TCPListener.
Exception:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at Test.Server.ProcessClient(Object client, Object clientId)
Server.cs
public class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public event EventHandler<EventLogArgs> EventLog;
public Server()
{
// Startup Code
ThreadPool.SetMinThreads(50, 50);
}
void UpdateEventLog(EventLogArgs e)
{
if (EventLog != null)
{
EventLog(this, e);
}
}
public void Start(string ip, int port_num)
{
Globals.listen = true;
Int32 port = port_num;
IPAddress address = IPAddress.Parse(ip);
this.tcpListener = new TcpListener(address, port);
Socket listenerSocket = this.tcpListener.Server;
LingerOption lingerOption = new LingerOption(true, 10);
listenerSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Linger,
lingerOption);
this.listenThread = new Thread(ListenForClients);
this.listenThread.Start();
UpdateEventLog(new EventLogArgs("Started server..."));
}
public void Stop()
{
Globals.listen = false;
UpdateEventLog(new EventLogArgs("Stop server request sent..."));
}
private void ListenForClients()
{
this.tcpListener.Start();
while (Globals.listen)
{
if (!this.tcpListener.Pending())
{
// This is so we can stop the server.
Thread.Sleep(25); // choose a number (in milliseconds) that makes sense
continue; // skip to next iteration of loop
}
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
Globals.clientRequests++;
int clientRequest = Globals.clientRequests;
UpdateEventLog(new EventLogArgs("(" + Globals.clientRequests + ") Client connected...\r\n"));
ThreadPool.QueueUserWorkItem(o => ProcessClient(client, clientRequest));
}
UpdateEventLog(new EventLogArgs("Stopped server!"));
this.tcpListener.Stop();
}
private void ProcessClient(object client, object clientId)
{
TcpClient tcpClient = (TcpClient)client;
int clientRequestId = (int)clientId;
NetworkStream clientStream = tcpClient.GetStream();
byte[] clientRequestRaw = new byte[1024];
int bytesRead;
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Process client request..."));
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(clientRequestRaw, 0, 512);
}
catch
{
//a socket error has occured
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") SOCKET ERROR\r\n\r\n" + e));
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Client disconnected from server, nothing sent."));
break;
}
//message has successfully been received.
ASCIIEncoding encoder = new ASCIIEncoding();
string clientRequest = encoder.GetString(clientRequestRaw, 0, bytesRead);
string[] cmd;
string success;
Dictionary<string, string> headers = new Dictionary<string, string>();
Dictionary<string, string> contents = new Dictionary<string, string>();
if (clientRequest.Length == 0)
{
return;
}
// Parse HTTP request
Parse Parse = new Parse();
Parse.HTTPRequest(clientRequest, out success, out cmd, out headers, out contents);
string response;
if (success == "TRUE")
{
response = "HTTP/1.1 200 OK\r\n\r\nHello World!\r\n";
}
else
{
response = "HTTP/1.1 200 OK\r\n\r\nHello Error!\r\n";
}
ResponseToClient(client, response);
clientStream.Close();
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Server response...\r\n\r\n" + response));
}
tcpClient.Close();
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Client disconnected."));
}
private void ResponseToClient(object client, string response)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(response);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
}
The Server class is started from the main thread like so:
this.server = new Server();
this.server.EventLog += new EventHandler<EventLogArgs>(UpdateEventLog);
ThreadPool.QueueUserWorkItem(o => this.server.Start("127.0.0.1", 3000));
What am I doing wrong here?
I have taken the while loop out from the ProcessClient() method and this seems to have fixed the problem. Thanks anyway.
private void ProcessClient(object client, object clientId)
{
TcpClient tcpClient = (TcpClient)client;
int clientRequestId = (int)clientId;
NetworkStream clientStream = tcpClient.GetStream();
byte[] clientRequestRaw = new byte[1024];
int bytesRead;
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Process client request..."));
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(clientRequestRaw, 0, 512);
}
catch (Exception e)
{
//a socket error has occured
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") SOCKET ERROR\r\n\r\n" + e));
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Client disconnected from server, nothing sent."));
break;
}
//message has successfully been received.
ASCIIEncoding encoder = new ASCIIEncoding();
string clientRequest = encoder.GetString(clientRequestRaw, 0, bytesRead);
string[] cmd;
string success;
Dictionary<string, string> headers = new Dictionary<string, string>();
Dictionary<string, string> contents = new Dictionary<string, string>();
if (clientRequest.Length == 0)
{
return;
}
// Parse HTTP request
Parse Parse = new Parse();
Parse.HTTPRequest(clientRequest, out success, out cmd, out headers, out contents);
string response;
if (success == "TRUE")
{
response = "HTTP/1.1 200 OK\r\n\r\nHello World!\r\n";
}
else
{
response = "HTTP/1.1 200 OK\r\n\r\nHello Error!\r\n";
}
ResponseToClient(client, response);
clientStream.Close();
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Server response...\r\n\r\n" + response));
}
tcpClient.Close();
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Client disconnected."));
}
You have to give the network right service.
Write services.msc in run,then find your service.
YourService->Properties-> Log On-> Log On as Network
Since you solved your problem I'm just gonna give you two hints:
First of all, do not use the thread pool to make synchronous operations asynchronous. It's a waste of resources. Use the asynchronous methods instead (BeginAccept/EndAccept etc).
Next break your class into multiple classes. One taking care of the server parts only and one taking care of the client parts only. It makes your code a lot easier to follow (even for you :)).
Anyway don't use if (success == "TRUE")!

Categories