C# Form .Net 4.7
A client app should receive XML data from an external payment machine. The XML is automatically sent after each deposit. It's about receiving it at any time and displaying it in a TextBox.
Sending takes place via TCP
The machine opens the connection to the external system at the specified port
Sends the data
Waits for confirmation on the same connection if necessary
Closes the connection
Since the client has to be able to receive the data at any time, I thought about a listener. But I'm not sure if this approach is the right one. What I did here doesn't work. I wanted to test that with a localhost. There is sure to be a simple solution. But since I'm not a network specialist, I can't find it. Does anyone know how to do it best?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace TCPListener
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
TcpListener Listener = null;
Int32 port = 8080;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
private void button1_Click(object sender, EventArgs e)
{
Listener = new TcpListener(localAddr, port);
byte[] receiveBuffer = new byte[10025];
while (true)
{
int requestCount = 0;
Listener.Start();
MessageBox.Show(" >> Listener Started");
using (var tcpClient = Listener.AcceptTcpClient())
{
MessageBox.Show(" >> Accepted connection from client");
using (var networkStream = tcpClient.GetStream())
{
while (true)
{
try
{
requestCount = requestCount++;
var bytesRead = networkStream.Read(receiveBuffer, 0, (int)tcpClient.ReceiveBufferSize);
if (bytesRead == 0)
{
// Read returns 0 if the client closes the connection
break;
}
string dataFromClient = System.Text.Encoding.ASCII.GetString(receiveBuffer, 0, bytesRead);
XmlDocument xm = new XmlDocument();
xm.LoadXml(string.Format("<root>{0}</root>", dataFromClient));
XmlElement root = xm.DocumentElement;
string rootName = root.FirstChild.Name;
textBox1.Text = (rootName, dataFromClient);
}
catch (Exception ex)
{
MessageBox.Show("ReceivePortMessages: " + ex.ToString());
break;
}
}
}
MessageBox.Show(" >> stopped read loop");
}
Listener.Stop();
}
}
}
}
Related
How can i get TCP Connection ID of all the connected clients.Actually i am making a program in c# (console application) that will return array with Connection Ids and IMEIs of connected clients. below code is simple client and server program so how can i get Connection id ?
Client Program :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net.Sockets;
namespace TcpEchoClient
{
class TcpEchoClient
{
static void Main(string[] args)
{
Console.Title = "TCP Client";
String server = "xxx.xxx.x.xx"; // IP address
byte[] byteBuffer = Encoding.ASCII.GetBytes("Test Message");
int servPort = 1;
TcpClient client = null;
NetworkStream netStream = null;
try
{
client = new TcpClient(server, servPort);
Console.WriteLine("Connected to server... sending echo string");
netStream = client.GetStream();
netStream.Write(byteBuffer, 0, byteBuffer.Length);
Console.WriteLine("Sent {0} bytes to server...", byteBuffer.Length);
int totalBytesRcvd = 0;
int bytesRcvd = 0;
while (totalBytesRcvd < byteBuffer.Length)
{
if ((bytesRcvd = netStream.Read(byteBuffer, totalBytesRcvd, byteBuffer.Length - totalBytesRcvd)) == 0)
{
Console.WriteLine("Connection closed prematurely.");
break;
}
totalBytesRcvd += bytesRcvd;
}
Console.WriteLine("Received {0} bytes from server: {1}", totalBytesRcvd, Encoding.ASCII.GetString(byteBuffer, 0, totalBytesRcvd));
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
netStream.Close();
client.Close();
}
}
}
}
Server Program :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
sing System.Net;
using System.Net.Sockets;
namespace TcpEchoServer
{
class TcpEchoServer
{
private const int BUFSIZE = 32;
static void Main(string[] args)
{
Console.Title = "TCP Server";
int servPort = 1;
TcpListener listener = null;
try
{
listener = new TcpListener(IPAddress.Any,servPort);
listener.Start();
}
catch(SocketException se)
{
Console.WriteLine(se.ErrorCode + ": " + se.Message);
Environment.Exit(se.ErrorCode);
}
byte[] rcvBuffer = new byte[BUFSIZE];
int bytesRcvd;
for (; ; )
{
TcpClient client = null;
NetworkStream netStream = null;
try
{
client = listener.AcceptTcpClient();
netStream = client.GetStream();
Console.Write("Handling client - ");
int totalBytesEchoed = 0;
while ((bytesRcvd = netStream.Read(rcvBuffer,0,rcvBuffer.Length)) >0)
{
netStream.Write(rcvBuffer,0,bytesRcvd);
totalBytesEchoed += bytesRcvd;
}
Console.WriteLine("echoed {0} bytes.", totalBytesEchoed);
netStream.Close();
client.Close();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
netStream.Close();
}
}
}
}
}
Can anyone point me in the right direction?
Thanks in advance.
I have written a client program using c# socket programming which will send a file to the server. Is there any way I can send a client ID (say: 1234) to the server so that the server can recognize different clients? What modification will I have to make in the following code?
// Client
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
namespace FileTransferClient
{
class Program
{
static void Main(string[] args)
{
try
{
string fileName = #"D:\demo.txt";
string p = Path.GetExtension(fileName);
FileInfo f = new FileInfo(fileName);
long s1 = f.Length;
TcpClient tcpClient = new TcpClient("127.0.0.1", 1234);
Console.WriteLine("Connected. Sending file.");
StreamWriter sWriter = new StreamWriter(tcpClient.GetStream());
byte[] bytes = File.ReadAllBytes(fileName);
sWriter.WriteLine(bytes.Length.ToString());
sWriter.Flush();
sWriter.WriteLine(fileName);
sWriter.Flush();
Console.WriteLine("Sending file");
tcpClient.Client.SendFile(fileName);
}
catch (Exception e)
{
Console.Write(e.Message);
}
Console.Read();
}
}
}
How do I make the client read from the stream (for messages of other clients sent to the stream) at the same time as being able to write to them?
I tried creating different threads on the client side (did I even do it right?), however I can still only write to the server, without any response. This is what I'm getting right now:
(Server-Client-Client)
Client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace Klientas
{
class Klientas
{
public static void Write()
{
while (true)
{
TcpClient clientSocket = new TcpClient("localhost", 1000);
string str = Console.ReadLine();
BinaryWriter writer = new BinaryWriter(clientSocket.GetStream());
writer.Write(str);
}
}
public static void Read()
{
while (true)
{
TcpClient clientSocket = new TcpClient("localhost", 1000);
BinaryReader reader = new BinaryReader(clientSocket.GetStream());
Console.WriteLine(reader.ReadString());
}
}
static void Main(string[] args){
Thread ctThread = new Thread(Write);
Thread ctThread2 = new Thread(Read);
ctThread2.Start();
ctThread.Start();
}
}
}
Server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.IO;
namespace MultiServeris
{
class Multiserveris
{
static void Main(string[] args)
{
TcpListener ServerSocket = new TcpListener(1000);
ServerSocket.Start();
Console.WriteLine("Server started.");
while (true)
{
TcpClient clientSocket = ServerSocket.AcceptTcpClient();
handleClient client = new handleClient();
client.startClient(clientSocket);
}
}
}
public class handleClient
{
TcpClient clientSocket;
public void startClient(TcpClient inClientSocket)
{
this.clientSocket = inClientSocket;
Thread ctThread = new Thread(Chat);
ctThread.Start();
}
private void Chat()
{
while (true)
{
BinaryReader reader = new BinaryReader(clientSocket.GetStream());
Console.WriteLine(reader.ReadString());
}
}
}
}
It seems like you do not have any code on the server to send messages to the client. You need to maintain a list of connected clients and make the server send a message to the eligible clients when it receives a message. Also do not make the client a console app. Unlike most projects for a chat client it is actually harder to do it as a console app.
To keep a list of clients you declare a list of TCP Clients like this
static List<TcpClient> clients = new List<TcpClient>();
Then when a client connects you add it to the list
TcpClient clientSocket = ServerSocket.AcceptTcpClient();
clients.Add(clientSocket);
Then when you receive a message you send it to all clients
BinaryReader reader = new BinaryReader(clientSocket.GetStream());
while(true)
{
string message = reader.ReadString();
foreach(var client in clients)
{
//send message to client
}
}
Now remember that in practice you should handle things like disconnects and adding and removing clients from the list should be thread safe (locks and all).
Good starting point for socket client-server communication: demo application and library. Support for reconnecting, sudden client disconnect catch, message broadcasting and many more.
hello guyz i have made a bare bone program in C# that simply sends a message from server to client.
Now i have successfully tested both programs running on the same machines. However when i attempt to connect 2 different computers on different networks it sends me the unable to connect message.
Here the server code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Net.Sockets;
namespace chat_client_console
{
class Program
{
static TcpListener listener;
static void Main(string[] args)
{
/*
string name = Dns.GetHostName();
IPAddress[] address = Dns.GetHostAddresses(name);
foreach(IPAddress addr in address)
{
Console.WriteLine(addr);
}
Console.WriteLine(address[2].ToString());*/
Console.WriteLine("server");
listener = new TcpListener(IPAddress.Any, 2055);
listener.Start();
Socket soc = listener.AcceptSocket();
Console.WriteLine("Connection successful");
Stream s = new NetworkStream(soc);
StreamReader sr = new StreamReader(s);
StreamWriter sw = new StreamWriter(s);
sw.AutoFlush = true;
sw.WriteLine("A test message");
sw.WriteLine("\n");
Console.WriteLine("Test message delivered. Now ending the program");
/*
string name = Dns.GetHostName();
Console.WriteLine(name);
//IPHostEntry ip = Dns.GetHostEntry(name);
//Console.WriteLine(ip.AddressList[0].ToString());
IPAddress[] adr=Dns.GetHostAddresses(name);
foreach (IPAddress adress in adr)
{
Console.WriteLine(adress);
}
*/
Console.ReadLine();
}
}
}
and here the client code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Sockets;
namespace chat_client_console_client
{
class Program
{
static void Main(string[] args)
{
string host_ip_address;
Console.WriteLine("Enter server ip address");
host_ip_address=Console.ReadLine();
string display;
TcpClient client = new TcpClient(host_ip_address, 2055);
Stream s = client.GetStream();
Console.WriteLine("Connection successfully received");
StreamWriter sw = new StreamWriter(s);
StreamReader sr = new StreamReader(s);
sw.AutoFlush = true;
/*while (true)
{
display = sr.ReadLine();
if (display == "")
{
Console.WriteLine("breaking stream");
break;
}
}*/
display = sr.ReadLine();
Console.WriteLine(display);
Console.ReadLine();
}
}
}
now when i enter the 127.0.0.1 in the client program it successfully connects to the server and the message is received.
However when i enter my external ip address in the client program running on another computer i am unable to connect.
Suggestions are required in this matter.
Thank you.
You can use Wireshark in the client computer and look up any tcp packet to make sure the message sent to server.
I searched a lot but all examples in the internet are console application. I've tried use console application example for windows forms but when I call socket.start form freezes and status changes to (not response). Also I tried multiple threads but it's unsuccessful too. If it is possible please advice me something.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace mserver1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ServerClass sc = new ServerClass();
sc.startServer(textBox1, richTextBox1);
}
}
public class ServerClass
{
public void startServer(TextBox tb, RichTextBox rb)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9939);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(ip);
socket.Listen(20);
rb.Text = rb.Text + "Waiting for client...";
Socket client = socket.Accept();
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
rb.Text = rb.Text + "Connected with " + clientep.Address + " at port " + clientep.Port;
string welcome = tb.Text;
byte[] data = new byte[1024];
data = Encoding.ASCII.GetBytes(welcome);
client.Send(data, data.Length, SocketFlags.None);
rb.Text = rb.Text + "Disconnected from" + clientep.Address;
client.Close();
socket.Close();
}
}
}
Thanks.
Your application will block until button1_Click returns.
You need to spawn a worker thread to do your listening. Additionally, you should not pass your controls directly into the worker thread. Rather, you should have a callback that will populate your controls with the data that comes from the socket communications.
Look up information on the BackgroundWorker. This will get you where you need to go.
I had the same problem, follow my solution for the SERVER
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SERVER_WIN
{
public partial class Form1 : Form
{
//Declare and Initialize the IP Adress
static IPAddress ipAd = IPAddress.Parse("10.1.42.31");
//Declare and Initilize the Port Number;
static int PortNumber = 8888;
/* Initializes the Listener */
TcpListener ServerListener = new TcpListener(ipAd, PortNumber);
TcpClient clientSocket = default(TcpClient);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Thread ThreadingServer = new Thread(StartServer);
ThreadingServer.Start();
}
private void THREAD_MOD(string teste)
{
txtStatus.Text += Environment.NewLine + teste;
}
private void StartServer()
{
Action<string> DelegateTeste_ModifyText = THREAD_MOD;
ServerListener.Start();
Invoke(DelegateTeste_ModifyText, "Server waiting connections!");
clientSocket = ServerListener.AcceptTcpClient();
Invoke(DelegateTeste_ModifyText, "Server ready!");
while (true)
{
try
{
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[20];
networkStream.Read(bytesFrom, 0, 20);
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
string serverResponse = "Received!";
Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
}
catch
{
ServerListener.Stop();
ServerListener.Start();
Invoke(DelegateTeste_ModifyText, "Server waiting connections!");
clientSocket = ServerListener.AcceptTcpClient();
Invoke(DelegateTeste_ModifyText, "Server ready!");
}
}
}
}
}
You will need to put in your windows forms just one control TextView, named txtStatus.
Client Program:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace CLIENT_WIN
{
public partial class Form1 : Form
{
TcpClient tcpclnt = new TcpClient();
//Declare and Initialize the IP Adress
IPAddress ipAd = IPAddress.Parse("10.1.42.31");
//Declare and Initilize the Port Number;
int PortNumber = 8888;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Console.WriteLine("Connecting.....");
try
{
tcpclnt.Connect(ipAd, PortNumber);
txtStatus.Text += Environment.NewLine + "Connected";
txtStatus.Text += Environment.NewLine + "Enter the string to be transmitted";
}
catch { }
}
private void btnEnviar_Click(object sender, EventArgs e)
{
String str = txtEnviar.Text + "$";
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
txtStatus.Text += Environment.NewLine + "Transmitting...";
//Console.WriteLine("Transmitting.....");
stm.Write(ba, 0, ba.Length);
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
string Response = Encoding.ASCII.GetString(bb);
txtStatus.Text += Environment.NewLine + "Response from server: " + Response;
}
}
}
For the Client you will need put some controls;
two TextViews (txtStatus and txtEnviar) and a button named btnEnviar, that is it!
You must run at first the Server, than you can run the client, if you need to stop the client, dont worry you can let the Server running.