Multiple connections with TcpClient, second connection always hangs/does nothing












0















So I have a TcpClient in a console app that is listening on port 9096. I want the client to be able to handle multiple connections (simultaneous or not). I also do not want to use Threads. I want to use async/await. I also need to be able to gracefully close the app during certain events, being careful not to lose any data. So I need a cancellation token. I have the code mostly working but there are two issues.



First, when the app starts listening and I send it data; everything works correctly as long as the sender is using the same initial connection to the app. Once a new connection (or socket I guess? not clear on the terminology) is established the app does not process the new data.



Second, when the terminate signal is given to the app and the token is cancelled the app does not close. I am not getting any exceptions and I cannot figure out what I an doing wrong.



I have looked all over and cannot find an example of a TcpClient that uses async/await with a cancellation token. I also cannot find an example that I have been able to get working that correct processes multiple connections, without using Threads or other complicated designs. I want the design as simple as possible with as little code as possible while still meeting my requirements. If using threads is the only way to do it I will, but I am soo close to getting it right I feel like I am just missing a little thing.



I am at my wits end trying to figure this out and have exhausted all my ideas.



EDIT: I moved the AcceptTcpClientAsync into the loop as suggested below and it did not change anything. App functions the same as before.



Program.cs



class Program
{
private static List<Task> _listeners = new List<Task>();
private static readonly CancellationTokenSource cancelSource = new CancellationTokenSource();

static void Main(string args)
{
Console.TreatControlCAsInput = false;
Console.CancelKeyPress += (o, e) => {
Console.WriteLine("Shutting down.");
cancelSource.Cancel();
};

Console.WriteLine("Started, press ctrl + c to terminate.");

_listeners.Add(Listen(cancelSource.Token));

cancelSource.Token.WaitHandle.WaitOne();
Task.WaitAll(_listeners.ToArray(), cancelSource.Token);
}
}


Listen



public async Task Listen(CancellationToken token){
var listener = new TcpListener(IPAddress.Parse("0.0.0.0"), 9096);
listener.Start();

Console.WriteLine("Listening on port 9096");

while (!token.IsCancellationRequested) {
// Also tried putting AcceptTcpClientAsync here.
await Task.Run(async () => {
var client = await listener.AcceptTcpClientAsync();
using (var stream = client.GetStream())
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
using (var streamWriter = new StreamWriter(stream, Encoding.UTF8)) {
while (!token.IsCancellationRequested) {
// DO WORK WITH DATA RECEIVED
vat data = await streamReader.ReadAsync();
await streamWriter.WriteLineAsync("Request received.");
}
}
});
}

Console.WriteLine("Stopped Accepting Requests.");
listener.Server.Close();
listener.Stop();
}









share|improve this question

























  • you may have to use a background-worker thread

    – JohnB
    Nov 24 '18 at 1:26
















0















So I have a TcpClient in a console app that is listening on port 9096. I want the client to be able to handle multiple connections (simultaneous or not). I also do not want to use Threads. I want to use async/await. I also need to be able to gracefully close the app during certain events, being careful not to lose any data. So I need a cancellation token. I have the code mostly working but there are two issues.



First, when the app starts listening and I send it data; everything works correctly as long as the sender is using the same initial connection to the app. Once a new connection (or socket I guess? not clear on the terminology) is established the app does not process the new data.



Second, when the terminate signal is given to the app and the token is cancelled the app does not close. I am not getting any exceptions and I cannot figure out what I an doing wrong.



I have looked all over and cannot find an example of a TcpClient that uses async/await with a cancellation token. I also cannot find an example that I have been able to get working that correct processes multiple connections, without using Threads or other complicated designs. I want the design as simple as possible with as little code as possible while still meeting my requirements. If using threads is the only way to do it I will, but I am soo close to getting it right I feel like I am just missing a little thing.



I am at my wits end trying to figure this out and have exhausted all my ideas.



EDIT: I moved the AcceptTcpClientAsync into the loop as suggested below and it did not change anything. App functions the same as before.



Program.cs



class Program
{
private static List<Task> _listeners = new List<Task>();
private static readonly CancellationTokenSource cancelSource = new CancellationTokenSource();

static void Main(string args)
{
Console.TreatControlCAsInput = false;
Console.CancelKeyPress += (o, e) => {
Console.WriteLine("Shutting down.");
cancelSource.Cancel();
};

Console.WriteLine("Started, press ctrl + c to terminate.");

_listeners.Add(Listen(cancelSource.Token));

cancelSource.Token.WaitHandle.WaitOne();
Task.WaitAll(_listeners.ToArray(), cancelSource.Token);
}
}


Listen



public async Task Listen(CancellationToken token){
var listener = new TcpListener(IPAddress.Parse("0.0.0.0"), 9096);
listener.Start();

Console.WriteLine("Listening on port 9096");

while (!token.IsCancellationRequested) {
// Also tried putting AcceptTcpClientAsync here.
await Task.Run(async () => {
var client = await listener.AcceptTcpClientAsync();
using (var stream = client.GetStream())
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
using (var streamWriter = new StreamWriter(stream, Encoding.UTF8)) {
while (!token.IsCancellationRequested) {
// DO WORK WITH DATA RECEIVED
vat data = await streamReader.ReadAsync();
await streamWriter.WriteLineAsync("Request received.");
}
}
});
}

Console.WriteLine("Stopped Accepting Requests.");
listener.Server.Close();
listener.Stop();
}









share|improve this question

























  • you may have to use a background-worker thread

    – JohnB
    Nov 24 '18 at 1:26














0












0








0








So I have a TcpClient in a console app that is listening on port 9096. I want the client to be able to handle multiple connections (simultaneous or not). I also do not want to use Threads. I want to use async/await. I also need to be able to gracefully close the app during certain events, being careful not to lose any data. So I need a cancellation token. I have the code mostly working but there are two issues.



First, when the app starts listening and I send it data; everything works correctly as long as the sender is using the same initial connection to the app. Once a new connection (or socket I guess? not clear on the terminology) is established the app does not process the new data.



Second, when the terminate signal is given to the app and the token is cancelled the app does not close. I am not getting any exceptions and I cannot figure out what I an doing wrong.



I have looked all over and cannot find an example of a TcpClient that uses async/await with a cancellation token. I also cannot find an example that I have been able to get working that correct processes multiple connections, without using Threads or other complicated designs. I want the design as simple as possible with as little code as possible while still meeting my requirements. If using threads is the only way to do it I will, but I am soo close to getting it right I feel like I am just missing a little thing.



I am at my wits end trying to figure this out and have exhausted all my ideas.



EDIT: I moved the AcceptTcpClientAsync into the loop as suggested below and it did not change anything. App functions the same as before.



Program.cs



class Program
{
private static List<Task> _listeners = new List<Task>();
private static readonly CancellationTokenSource cancelSource = new CancellationTokenSource();

static void Main(string args)
{
Console.TreatControlCAsInput = false;
Console.CancelKeyPress += (o, e) => {
Console.WriteLine("Shutting down.");
cancelSource.Cancel();
};

Console.WriteLine("Started, press ctrl + c to terminate.");

_listeners.Add(Listen(cancelSource.Token));

cancelSource.Token.WaitHandle.WaitOne();
Task.WaitAll(_listeners.ToArray(), cancelSource.Token);
}
}


Listen



public async Task Listen(CancellationToken token){
var listener = new TcpListener(IPAddress.Parse("0.0.0.0"), 9096);
listener.Start();

Console.WriteLine("Listening on port 9096");

while (!token.IsCancellationRequested) {
// Also tried putting AcceptTcpClientAsync here.
await Task.Run(async () => {
var client = await listener.AcceptTcpClientAsync();
using (var stream = client.GetStream())
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
using (var streamWriter = new StreamWriter(stream, Encoding.UTF8)) {
while (!token.IsCancellationRequested) {
// DO WORK WITH DATA RECEIVED
vat data = await streamReader.ReadAsync();
await streamWriter.WriteLineAsync("Request received.");
}
}
});
}

Console.WriteLine("Stopped Accepting Requests.");
listener.Server.Close();
listener.Stop();
}









share|improve this question
















So I have a TcpClient in a console app that is listening on port 9096. I want the client to be able to handle multiple connections (simultaneous or not). I also do not want to use Threads. I want to use async/await. I also need to be able to gracefully close the app during certain events, being careful not to lose any data. So I need a cancellation token. I have the code mostly working but there are two issues.



First, when the app starts listening and I send it data; everything works correctly as long as the sender is using the same initial connection to the app. Once a new connection (or socket I guess? not clear on the terminology) is established the app does not process the new data.



Second, when the terminate signal is given to the app and the token is cancelled the app does not close. I am not getting any exceptions and I cannot figure out what I an doing wrong.



I have looked all over and cannot find an example of a TcpClient that uses async/await with a cancellation token. I also cannot find an example that I have been able to get working that correct processes multiple connections, without using Threads or other complicated designs. I want the design as simple as possible with as little code as possible while still meeting my requirements. If using threads is the only way to do it I will, but I am soo close to getting it right I feel like I am just missing a little thing.



I am at my wits end trying to figure this out and have exhausted all my ideas.



EDIT: I moved the AcceptTcpClientAsync into the loop as suggested below and it did not change anything. App functions the same as before.



Program.cs



class Program
{
private static List<Task> _listeners = new List<Task>();
private static readonly CancellationTokenSource cancelSource = new CancellationTokenSource();

static void Main(string args)
{
Console.TreatControlCAsInput = false;
Console.CancelKeyPress += (o, e) => {
Console.WriteLine("Shutting down.");
cancelSource.Cancel();
};

Console.WriteLine("Started, press ctrl + c to terminate.");

_listeners.Add(Listen(cancelSource.Token));

cancelSource.Token.WaitHandle.WaitOne();
Task.WaitAll(_listeners.ToArray(), cancelSource.Token);
}
}


Listen



public async Task Listen(CancellationToken token){
var listener = new TcpListener(IPAddress.Parse("0.0.0.0"), 9096);
listener.Start();

Console.WriteLine("Listening on port 9096");

while (!token.IsCancellationRequested) {
// Also tried putting AcceptTcpClientAsync here.
await Task.Run(async () => {
var client = await listener.AcceptTcpClientAsync();
using (var stream = client.GetStream())
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
using (var streamWriter = new StreamWriter(stream, Encoding.UTF8)) {
while (!token.IsCancellationRequested) {
// DO WORK WITH DATA RECEIVED
vat data = await streamReader.ReadAsync();
await streamWriter.WriteLineAsync("Request received.");
}
}
});
}

Console.WriteLine("Stopped Accepting Requests.");
listener.Server.Close();
listener.Stop();
}






c# .net .net-core tcpclient tcplistener






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 24 '18 at 2:29







Jason R

















asked Nov 24 '18 at 1:24









Jason RJason R

11




11













  • you may have to use a background-worker thread

    – JohnB
    Nov 24 '18 at 1:26



















  • you may have to use a background-worker thread

    – JohnB
    Nov 24 '18 at 1:26

















you may have to use a background-worker thread

– JohnB
Nov 24 '18 at 1:26





you may have to use a background-worker thread

– JohnB
Nov 24 '18 at 1:26












1 Answer
1






active

oldest

votes


















0














This is actually working the way you designed it, however you have only built to receive one connection. I am not going to write a full socket implementation for you (as this can get fairly in-depth). However, as for you main problem, you need to put the AcceptTcpClientAsync in the loop otherwise you wont get any more connections



var cancellation = new CancellationTokenSource();

...

var listener = new TcpListener(...);
listener.Start();
try
{
while (!token.IsCancellationRequested)
{
var client = await listener.AcceptTcpClientAsync()
...
}
}
finally
{
listener.Stop();
}

// somewhere in another thread
cancellation.Cancel();


Update




I tried that and no behavior changed. Still does not pick up any
connection after the first.




 await ...
while (!token.IsCancellationRequested) {
// DO WORK WITH DATA RECEIVED


Its obvious that AcceptTcpClientAsync will never get called again because you are awaiting the task. This method is what accepts the client, if you cant call it, you dont get any more clients.



You cannot block here, which is what you are doing. Please see some socket server examples to get a better idea of how to write a listener






share|improve this answer


























  • I tried that and no behavior changed. Still does not pick up any connection after the first.

    – Jason R
    Nov 24 '18 at 2:30











  • @JasonR updated

    – TheGeneral
    Nov 24 '18 at 2:48











  • @JasonR i missed the most import bit, you are awaiting the task, remove the await and it will work, with the AcceptTcpClientAsync in the right place

    – TheGeneral
    Nov 24 '18 at 2:53













  • @JasonR here is another example gist.github.com/Maxwe11/cf8cc6331ad73671846e

    – TheGeneral
    Nov 24 '18 at 2:56













  • OMG! How simple. I cannot believe I missed that. It makes sense in hindsight and I understand everything. Just completely escaped me until you said it. Thanks.

    – Jason R
    Nov 24 '18 at 4:32











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53454397%2fmultiple-connections-with-tcpclient-second-connection-always-hangs-does-nothing%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














This is actually working the way you designed it, however you have only built to receive one connection. I am not going to write a full socket implementation for you (as this can get fairly in-depth). However, as for you main problem, you need to put the AcceptTcpClientAsync in the loop otherwise you wont get any more connections



var cancellation = new CancellationTokenSource();

...

var listener = new TcpListener(...);
listener.Start();
try
{
while (!token.IsCancellationRequested)
{
var client = await listener.AcceptTcpClientAsync()
...
}
}
finally
{
listener.Stop();
}

// somewhere in another thread
cancellation.Cancel();


Update




I tried that and no behavior changed. Still does not pick up any
connection after the first.




 await ...
while (!token.IsCancellationRequested) {
// DO WORK WITH DATA RECEIVED


Its obvious that AcceptTcpClientAsync will never get called again because you are awaiting the task. This method is what accepts the client, if you cant call it, you dont get any more clients.



You cannot block here, which is what you are doing. Please see some socket server examples to get a better idea of how to write a listener






share|improve this answer


























  • I tried that and no behavior changed. Still does not pick up any connection after the first.

    – Jason R
    Nov 24 '18 at 2:30











  • @JasonR updated

    – TheGeneral
    Nov 24 '18 at 2:48











  • @JasonR i missed the most import bit, you are awaiting the task, remove the await and it will work, with the AcceptTcpClientAsync in the right place

    – TheGeneral
    Nov 24 '18 at 2:53













  • @JasonR here is another example gist.github.com/Maxwe11/cf8cc6331ad73671846e

    – TheGeneral
    Nov 24 '18 at 2:56













  • OMG! How simple. I cannot believe I missed that. It makes sense in hindsight and I understand everything. Just completely escaped me until you said it. Thanks.

    – Jason R
    Nov 24 '18 at 4:32
















0














This is actually working the way you designed it, however you have only built to receive one connection. I am not going to write a full socket implementation for you (as this can get fairly in-depth). However, as for you main problem, you need to put the AcceptTcpClientAsync in the loop otherwise you wont get any more connections



var cancellation = new CancellationTokenSource();

...

var listener = new TcpListener(...);
listener.Start();
try
{
while (!token.IsCancellationRequested)
{
var client = await listener.AcceptTcpClientAsync()
...
}
}
finally
{
listener.Stop();
}

// somewhere in another thread
cancellation.Cancel();


Update




I tried that and no behavior changed. Still does not pick up any
connection after the first.




 await ...
while (!token.IsCancellationRequested) {
// DO WORK WITH DATA RECEIVED


Its obvious that AcceptTcpClientAsync will never get called again because you are awaiting the task. This method is what accepts the client, if you cant call it, you dont get any more clients.



You cannot block here, which is what you are doing. Please see some socket server examples to get a better idea of how to write a listener






share|improve this answer


























  • I tried that and no behavior changed. Still does not pick up any connection after the first.

    – Jason R
    Nov 24 '18 at 2:30











  • @JasonR updated

    – TheGeneral
    Nov 24 '18 at 2:48











  • @JasonR i missed the most import bit, you are awaiting the task, remove the await and it will work, with the AcceptTcpClientAsync in the right place

    – TheGeneral
    Nov 24 '18 at 2:53













  • @JasonR here is another example gist.github.com/Maxwe11/cf8cc6331ad73671846e

    – TheGeneral
    Nov 24 '18 at 2:56













  • OMG! How simple. I cannot believe I missed that. It makes sense in hindsight and I understand everything. Just completely escaped me until you said it. Thanks.

    – Jason R
    Nov 24 '18 at 4:32














0












0








0







This is actually working the way you designed it, however you have only built to receive one connection. I am not going to write a full socket implementation for you (as this can get fairly in-depth). However, as for you main problem, you need to put the AcceptTcpClientAsync in the loop otherwise you wont get any more connections



var cancellation = new CancellationTokenSource();

...

var listener = new TcpListener(...);
listener.Start();
try
{
while (!token.IsCancellationRequested)
{
var client = await listener.AcceptTcpClientAsync()
...
}
}
finally
{
listener.Stop();
}

// somewhere in another thread
cancellation.Cancel();


Update




I tried that and no behavior changed. Still does not pick up any
connection after the first.




 await ...
while (!token.IsCancellationRequested) {
// DO WORK WITH DATA RECEIVED


Its obvious that AcceptTcpClientAsync will never get called again because you are awaiting the task. This method is what accepts the client, if you cant call it, you dont get any more clients.



You cannot block here, which is what you are doing. Please see some socket server examples to get a better idea of how to write a listener






share|improve this answer















This is actually working the way you designed it, however you have only built to receive one connection. I am not going to write a full socket implementation for you (as this can get fairly in-depth). However, as for you main problem, you need to put the AcceptTcpClientAsync in the loop otherwise you wont get any more connections



var cancellation = new CancellationTokenSource();

...

var listener = new TcpListener(...);
listener.Start();
try
{
while (!token.IsCancellationRequested)
{
var client = await listener.AcceptTcpClientAsync()
...
}
}
finally
{
listener.Stop();
}

// somewhere in another thread
cancellation.Cancel();


Update




I tried that and no behavior changed. Still does not pick up any
connection after the first.




 await ...
while (!token.IsCancellationRequested) {
// DO WORK WITH DATA RECEIVED


Its obvious that AcceptTcpClientAsync will never get called again because you are awaiting the task. This method is what accepts the client, if you cant call it, you dont get any more clients.



You cannot block here, which is what you are doing. Please see some socket server examples to get a better idea of how to write a listener







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 24 '18 at 2:54

























answered Nov 24 '18 at 2:13









TheGeneralTheGeneral

28.2k63365




28.2k63365













  • I tried that and no behavior changed. Still does not pick up any connection after the first.

    – Jason R
    Nov 24 '18 at 2:30











  • @JasonR updated

    – TheGeneral
    Nov 24 '18 at 2:48











  • @JasonR i missed the most import bit, you are awaiting the task, remove the await and it will work, with the AcceptTcpClientAsync in the right place

    – TheGeneral
    Nov 24 '18 at 2:53













  • @JasonR here is another example gist.github.com/Maxwe11/cf8cc6331ad73671846e

    – TheGeneral
    Nov 24 '18 at 2:56













  • OMG! How simple. I cannot believe I missed that. It makes sense in hindsight and I understand everything. Just completely escaped me until you said it. Thanks.

    – Jason R
    Nov 24 '18 at 4:32



















  • I tried that and no behavior changed. Still does not pick up any connection after the first.

    – Jason R
    Nov 24 '18 at 2:30











  • @JasonR updated

    – TheGeneral
    Nov 24 '18 at 2:48











  • @JasonR i missed the most import bit, you are awaiting the task, remove the await and it will work, with the AcceptTcpClientAsync in the right place

    – TheGeneral
    Nov 24 '18 at 2:53













  • @JasonR here is another example gist.github.com/Maxwe11/cf8cc6331ad73671846e

    – TheGeneral
    Nov 24 '18 at 2:56













  • OMG! How simple. I cannot believe I missed that. It makes sense in hindsight and I understand everything. Just completely escaped me until you said it. Thanks.

    – Jason R
    Nov 24 '18 at 4:32

















I tried that and no behavior changed. Still does not pick up any connection after the first.

– Jason R
Nov 24 '18 at 2:30





I tried that and no behavior changed. Still does not pick up any connection after the first.

– Jason R
Nov 24 '18 at 2:30













@JasonR updated

– TheGeneral
Nov 24 '18 at 2:48





@JasonR updated

– TheGeneral
Nov 24 '18 at 2:48













@JasonR i missed the most import bit, you are awaiting the task, remove the await and it will work, with the AcceptTcpClientAsync in the right place

– TheGeneral
Nov 24 '18 at 2:53







@JasonR i missed the most import bit, you are awaiting the task, remove the await and it will work, with the AcceptTcpClientAsync in the right place

– TheGeneral
Nov 24 '18 at 2:53















@JasonR here is another example gist.github.com/Maxwe11/cf8cc6331ad73671846e

– TheGeneral
Nov 24 '18 at 2:56







@JasonR here is another example gist.github.com/Maxwe11/cf8cc6331ad73671846e

– TheGeneral
Nov 24 '18 at 2:56















OMG! How simple. I cannot believe I missed that. It makes sense in hindsight and I understand everything. Just completely escaped me until you said it. Thanks.

– Jason R
Nov 24 '18 at 4:32





OMG! How simple. I cannot believe I missed that. It makes sense in hindsight and I understand everything. Just completely escaped me until you said it. Thanks.

– Jason R
Nov 24 '18 at 4:32


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53454397%2fmultiple-connections-with-tcpclient-second-connection-always-hangs-does-nothing%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

Calculate evaluation metrics using cross_val_predict sklearn

Insert data from modal to MySQL (multiple modal on website)