Program hangs, waiting for input that I can never give - c#

I'm using visual studio to program this small TcpServer.
It's really specific. The server listens to port 1234 and is located on IP 127.0.0.1
Our teachers gave us a program that tries to connect to that port on that IP when you click "connect". It's working for everyone else, so it must be a coding error on my part.
When I click connect, the program sends the word "GET" over the stream, to which I have to respons with a list of allready connected IP-adress and then a newline containing only a .
When I disconnect, the program sends the word "REM" and I simply have to remove if from my list(which is a generic list)
I have a class TCPServer(we had to make our own), which has this as main code:
this.tl = new TcpListener(IPAddress.Any, PORT);
tl.Start();
while(true)
{
TcpClient tcl = tl.AcceptTcpClient();//here the server will wait forever untill someone connects, meaning the "new Thread" statement is never reached untill someone connects.
TcpHelper th = new TcpHelper(tcl,conf);
new Thread(new ThreadStart(th.Start)).Start();//should be multi-threaded, not sure if it is.
//t.Start();
}
TcpHelper looks like this(look for the commented text "here's the problem" within the usings):
public class TcpHelper
{
private TcpClient tc;
private IPEndPoint ipe;
private string get;
private Configuration conf;
public TcpHelper(TcpClient tc, Configuration conf)
{
this.tc = tc;
this.conf = conf;
}
public void Start()
{
using (NetworkStream nws = this.tc.GetStream())
{
using (StreamReader sr = new StreamReader(nws))
{
using (StreamWriter sw = new StreamWriter(nws))
{
this.ipe = (IPEndPoint)tc.Client.RemoteEndPoint;
this.conf.List.Add(this.ipe.Address);
bool conn = true;
while (conn)
{
this.get = sr.ReadLine();//here's the problem
switch (this.get)
{
case "GET":
foreach (IPAddress address in this.conf.Lijst)
{
sw.WriteLine(address.ToString());
}
sw.WriteLine(".");
break;
case "REM":
this.conf.List.Remove(this.ipe.Address);
sw.WriteLine("OK.");
conn = false;
break;
default:
break;
}
}
}
}
}
}
#region Properties
public IPEndPoint Ipe
{
get
{
return this.ipe;
}
}
#endregion
}

My guess is that your problem is that you're calling sr.ReadLine(), but the input does not contain a newline, so it's blocked there waiting for a newline that will never come.
you may want to try calling StreamReader.Read 3 times to build up the command string (GET/REM) before you act on it. (Note: 3 times is because all commands are three characters).
Read will return integers, but after checking that they are not -1 (indicating end-of-file), you can cast that integer to a char.

Sorry, maybe I'm not understanding this... Did you write this code?
this.tl = new TcpListener(IPAddress.Any, PORT);
tl.Start();
while(true)
{
TcpClient tcl = tl.AcceptTcpClient();
TcpHelper th = new TcpHelper(tcl,conf);
new Thread(new ThreadStart(th.Start)).Start();
//t.Start();
}
This is going to blow the **** out of any computer. You're looping infinitely, creating new threads on each loop. So, if you create one new thread per loop, and each loop takes one millisecond (lets say its very slow!), in five seconds you've got 5,000 threads. Each trying to listen at the same port.
Try using a single thread. If this is a console app, use Console.ReadLine() to block the main thread until somebody presses the enter key.
With the new information... AcceptTcpClient blocks, but instead of creating a new thread the work should be queued on the ThreadPool.

Related

How to solve infinite loop to show Window?

I'm trying to create my own chat app as a school project.
I have almost everything ready, connected with DB, backend. The only thing that is weighing me down right now is adding a TCP Server to the project for communication between Clients.
It's not supposed to be anything big, so just short code, plus I don't have that much experience with TCP in C#.
The code works, but the problem is that the Application/Window doesn't appear.
I suspected that the problem might be in the MainWindow() constructor due to the infinite loop (this was also confirmed here on SO). Unfortunately I don't know how to fix it anymore. I first had the server as a separate class, but I ran into this problem. So I tried implementing it directly in the class, or breaking the connection after shutting down the application.
public partial class MainWindow: Window {
private TcpListener myServer;
private bool isRunning;
public MainWindow() {
InitializeComponent();
myServer = new TcpListener(IPAddress.Any, 65525);
myServer.Start();
isRunning = true;
LoopServer();
}
private void LoopServer() {
while (isRunning) {
TcpClient client = myServer.AcceptTcpClient();
Thread thread = new Thread(new ParameterizedThreadStart(LoopClient));
thread.Start(client);
}
}
private void LoopClient(object obj) {
TcpClient client = (TcpClient) obj;
StreamReader reader = new StreamReader(client.GetStream(), Encoding.UTF8);
StreamWriter writer = new StreamWriter(client.GetStream(), Encoding.UTF8);
MessageBox.Show("Connected bro!");
writer.Flush();
bool clientRunning = true;
while (clientRunning) {
string data = reader.ReadLine();
MessageBox.Show(data);
writer.Flush();
}
}
}
An infinite loop is okay for a server to be running in. Generally, you can start up the server (1st application). The clients (different application) can connect to it and then process messages and broadcast them to all the clients appropriately.
Super simple example: Build Chat in C#
Alternatively you can try an event based approach to the TCP listener.

Is there a way to Check if something is written except waiting till something is written with "Console.ReadLine()"

I'm doing a TCP Messenger Programm ATM with TCPClient and TCPListener. Everything is working fine. I've had both of these in separate programs and now I'm basically trying to make it one Program. I'm stuck with the fact that it is always WAITING till I have something written to send it before it goes to checking the receive. I'm new to C# and learning. So I need a way to check "is something written? If no, then skip this" basically a bool to ask if something is written.
I've tried to make it like "if the line in storage right now is the same as the was the last time, skip it" so it doesnt stuck infinitly in the Send sector of the program. But still it ALWAYS waits until I wrote something before it even checks/ skips it.
This is the write and send loop code:
nachricht = Console.ReadLine();
if (nachrichtcheck != nachricht)
{
Console.WriteLine("test1");
TcpClient clientnachricht = new TcpClient(zielip, port);
NetworkStream streamnachricht = clientnachricht.GetStream();
sendnachricht = Encoding.ASCII.GetBytes(nachricht);
streamnachricht.Write(sendnachricht, 0, sendnachricht.Length);
streamnachricht.Close();
clientnachricht.Close();
nachrichtcheck = nachricht;
Console.WriteLine("test2");
}
else
{
if (empfangstream.CanRead)
{
Console.WriteLine("test3");
byte[] receivedBuffer2 = new byte[100];
NetworkStream stream = empfangclient.GetStream();
stream.Read(receivedBuffer, 0, receivedBuffer.Length);
StringBuilder msg2 = new StringBuilder();
foreach (byte b in receivedBuffer)
{
if (b.Equals(00))
{
break;
}
else
msg2.Append(Convert.ToChar(b).ToString());
}
Console.WriteLine("test4");
empfangscheck2 = msg2.ToString();
if (empfangscheck2 != empfangscheck)
{
Console.WriteLine(msg2.ToString());
empfangscheck = msg2.ToString();
Console.WriteLine("receive");
}
}
}
So if someone can help me just getting a way to get a bool to check if something is written -> then use it. Except of wait until something is written -> use it it would help me miles.
I've got an alternative to solve your problem. You can use a thread to wait for an user input instead of your actual code.
(I've also considered your german language)
Code Example:
using System;
using System.Threading;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
string nachricht = "";
double AndereTätigkeitBeweis = 0;
Thread NachrichtenEinleser = new Thread(()=> {
Console.Write("Gib diene zu sendende Nachricht ein: ");//Type in the message you'd like to send
nachricht = Console.ReadLine();//Read the user Input without stopping the actual code because it's another process
});
NachrichtenEinleser.Start();
//do somewhat activity until you get a user input
while (nachricht == ""){
AndereTätigkeitBeweis++;
}
//Write out the user input
Console.WriteLine($"User Input: {nachricht}|AndereTätigkeitBeweis: {AndereTätigkeitBeweis}");
Console.ReadLine();
}
}
}
Output example:
Gib diene zu sendende Nachricht ein: hallo
User Input: hallo|AndereTätigkeitBeweis: 560075647
Hope this helps.

C# TCP/IP not working properly

I am working on a windows service that should collect all incoming TCP/IP streams with this class. It gets started from the services OnStart() void.
However I have encountered that when messages come in from a second sender, the whole communication stops working. The service then does not react to a single connection until you restart it.
public class TCPIP
{
public static Receiver rc = new Receiver();
public class Receiver
{
public delegate void ReceivedEventHandler(string ReceivedText, string Sender);
public event ReceivedEventHandler Received;
public void Start()
{
System.Threading.Thread th = new System.Threading.Thread(internals);
th.Start();
}
private void internals()
{
TcpListener _listener = new TcpListener(1994);
_listener.Start();
while (true)
{
TcpClient rcclient = _listener.AcceptTcpClient();
StreamReader reader = new StreamReader(rcclient.GetStream());
string msg = "";
while (reader.Peek() > -1)
{
msg += Convert.ToChar(reader.Read()).ToString();
}
Received(msg, rcclient.Client.RemoteEndPoint.ToString().Split(Convert.ToChar(":"))[0]);
// Cleanup
rcclient.Close();
reader.Close();
}
}
Could anybody help me out improving this class to answer connections from multiple endpoints, and to not be occupied after one?
Thank you very much in advance.
Just create a thread when you accept some connection, so if it's blocked will not afect the main program.
Btw you can try AcceptTcpClientAsync to prevent blocking calls.

C# TcpListener AcceptSocket does not work in separate thread

I have a simple TCP server based on the TcpListener. Since I want to use it in a Windows Form application I made it run in a separate thread as follows:
public void Start() {
this.serverThread = new Thread(new ThreadStart(this.ThreadProcess));
this.serverThread.Name = "Tcp-Server";
this.serverThread.Start();
}
protected void ThreadProcess() {
try
{
IPAddress ipAd = IPAddress.Parse("169.254.42.86");
this.listener = new TcpListener(ipAd, this.port);
this.listener.Start();
Socket mySocket = this.listener.AcceptSocket();
while (true)
{
if (mySocket.Connected)
{
byte[] RecvBytes = new byte[8192];
int byteNo = mySocket.Receive(RecvBytes, RecvBytes.Length, 0);
ASCIIEncoding asen = new ASCIIEncoding();
mySocket.Send(asen.GetBytes("srv reply msg"));
}
else
{
WriteLine("socket not connected.");
}
}
}
finally {
StopListener();
}
}
If I use this server in a console application as:
static void Main(string[] args)
{
try
{
int port = 8001;
Server server = new Server(port);
server.Start();
while (true) {
//server is running in separate thread
}
...
everything works as expected. However, when I try to include it in a Windows-Form Application that starts the server when a button is clicked, the code doesn't work any more. The server thread is being launched, but it doesn't accept any sockets.
Is there something that I am missing? I have been searching high and low on google without result...
Thanks for any help!
Not really an answer but too much to type in the comments:
The easiest way to debug this issue is to simply call the ThreadProcess() method in the same thread:
public void Start() {
ThreadProcess();
//this.serverThread = new Thread(new ThreadStart(this.ThreadProcess));
//this.serverThread.Name = "Tcp-Server";
//this.serverThread.Start();
}
You can then step through your code to see what happens. As soon as you hit the this.listener.AcceptSocket(); line your application will block, but you should be able to connect to it.
Usually the problem is something silly everyone overlooks like the Start() method not being called.

threaded serial port IOException when writing

I'm trying to write a small application that simply reads data from a socket, extracts some information (two integers) from the data and sends the extracted information off on a serial port.
The idea is that it should start and just keep going. In short, it works, but not for long. After a consistently short period I start to receive IOExceptions and socket receive buffer is swamped.
The thread framework has been taken from the MSDN serial port example.
The delay in send(), readThread.Join(), is an effort to delay read() in order to allow serial port interrupt processing a chance to occur, but I think I've misinterpreted the join function. I either need to sync the processes more effectively or throw some data away as it comes in off the socket, which would be fine. The integer data is controlling a pan tilt unit and I'm sure four times a second would be acceptable, but not sure on how to best acheive either, any ideas would be greatly appreciated, cheers.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static bool _continue;
static SerialPort _serialPort;
static Thread readThread;
static Thread sendThread;
static String sendString;
static Socket s;
static int byteCount;
static Byte[] bytesReceived;
// synchronise send and receive threads
static bool dataReceived;
const int FIONREAD = 0x4004667F;
static void Main(string[] args)
{
dataReceived = false;
readThread = new Thread(Read);
sendThread = new Thread(Send);
bytesReceived = new Byte[16384];
// Create a new SerialPort object with default settings.
_serialPort = new SerialPort("COM4", 38400, Parity.None, 8, StopBits.One);
// Set the read/write timeouts
_serialPort.WriteTimeout = 500;
_serialPort.Open();
string moveMode = "CV ";
_serialPort.WriteLine(moveMode);
s = null;
IPHostEntry hostEntry = Dns.GetHostEntry("localhost");
foreach (IPAddress address in hostEntry.AddressList)
{
IPEndPoint ipe = new IPEndPoint(address, 10001);
Socket tempSocket =
new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
tempSocket.Connect(ipe);
if (tempSocket.Connected)
{
s = tempSocket;
s.ReceiveBufferSize = 16384;
break;
}
else
{
continue;
}
}
readThread.Start();
sendThread.Start();
while (_continue)
{
Thread.Sleep(10);
;// Console.WriteLine("main...");
}
readThread.Join();
_serialPort.Close();
s.Close();
}
public static void Read()
{
while (_continue)
{
try
{
//Console.WriteLine("Read");
if (!dataReceived)
{
byte[] outValue = BitConverter.GetBytes(0);
// Check how many bytes have been received.
s.IOControl(FIONREAD, null, outValue);
uint bytesAvailable = BitConverter.ToUInt32(outValue, 0);
if (bytesAvailable > 0)
{
Console.WriteLine("Read thread..." + bytesAvailable);
byteCount = s.Receive(bytesReceived);
string str = Encoding.ASCII.GetString(bytesReceived);
//str = Encoding::UTF8->GetString( bytesReceived );
string[] split = str.Split(new Char[] { '\t', '\r', '\n' });
string filteredX = (split.GetValue(7)).ToString();
string filteredY = (split.GetValue(8)).ToString();
string[] AzSplit = filteredX.Split(new Char[] { '.' });
filteredX = (AzSplit.GetValue(0)).ToString();
string[] ElSplit = filteredY.Split(new Char[] { '.' });
filteredY = (ElSplit.GetValue(0)).ToString();
// scale values
int x = (int)(Convert.ToInt32(filteredX) * 1.9);
string scaledAz = x.ToString();
int y = (int)(Convert.ToInt32(filteredY) * 1.9);
string scaledEl = y.ToString();
String moveAz = "PS" + scaledAz + " ";
String moveEl = "TS" + scaledEl + " ";
sendString = moveAz + moveEl;
dataReceived = true;
}
}
}
catch (TimeoutException) {Console.WriteLine("timeout exception");}
catch (NullReferenceException) {Console.WriteLine("Read NULL reference exception");}
}
}
public static void Send()
{
while (_continue)
{
try
{
if (dataReceived)
{
// sleep Read() thread to allow serial port interrupt processing
readThread.Join(100);
// send command to PTU
dataReceived = false;
Console.WriteLine(sendString);
_serialPort.WriteLine(sendString);
}
}
catch (TimeoutException) { Console.WriteLine("Timeout exception"); }
catch (IOException) { Console.WriteLine("IOException exception"); }
catch (NullReferenceException) { Console.WriteLine("Send NULL reference exception"); }
}
}
}
}
UPDATE:
Thanks for the response Jon.
What I'm attempting to do is poll a socket for data, if its there process it and send it to the serial port, else keep polling the socket , repeating this whole process ad nauseum.
My initial attempt used a single thread and I was getting the same problem, which led me to believe that I need to give the serial port some more time to allow it to send the data before giving it more data on the next loop, because once I've sent data to the serial port I'm back polling the socket very hard. Having said that IOExceptions occur after approximately 30 seconds of operation, possibly with what I'm saying is I should see IOExceptions immediately?
My interpretation of the join function, I think, is incorrect, ideally calling readThread.Join from send() would allow read() to sleep while still pumping the COM port, but where I have it seems to put the send() to sleep, which I guess is the calling function?? and not producing the desired result.
I've encountered this problem recently as well (and a lot of others have too) - and it's basically a problem with Microsoft's serial port initialization code. I've written a very detailed explanation here if you wish to find out more. I've also suggested a workaround. Hopefully there's enough fuss about this issue such that Microsoft would take notice and fix it asap - perhaps a .NET 4.0 hotfix. This issue has been going on long enough starting .NET 2.0 (first time System.IO.Ports namespace was introduced).
It looks like what you're trying to do is send some data, then wait for a response, then repeat. You're using two threads for this and trying to sync them. I think you only need one thread. First send, then wait for a response, then repeat. This will eliminate your thread sync problems.

Categories