我有这个代码......
internal static void Start()
{
TcpListener listenerSocket = new TcpListener(IPAddress.Any, 32599);
listenerSocket.Start();
listenerSocket.BeginAcceptTcpClient(new AsyncCallback(AcceptClient), null);
}
Run Code Online (Sandbox Code Playgroud)
然后我的回调函数看起来像这样......
private static void AcceptClient(IAsyncResult asyncResult)
{
MessageHandler handler = new MessageHandler(listenerSocket.EndAcceptTcpClient(asyncResult));
ThreadPool.QueueUserWorkItem((object state) => handler.Process());
listenerSocket.BeginAcceptTcpClient(new AsyncCallback(AcceptClient), null);
}
Run Code Online (Sandbox Code Playgroud)
现在,我调用BeginAcceptTcpClient,然后一段时间后我想停止服务器.为此,我一直在调用TcpListener.Stop()或TcpListener.Server.Close().然而,这两个都执行我的AcceptClient函数.这会在我调用EndAcceptTcpClient时抛出异常.围绕这个的最佳做法是什么?一旦我调用了stop,我就可以放入一个标志来停止执行AcceptClient,但我想知道我是否遗漏了一些东西.
更新1
目前我通过将代码更改为这样来修补它.
private static void AcceptClient(IAsyncResult asyncResult)
{
if (!shutdown)
{
MessageHandler handler = new MessageHandler(listenerSocket.EndAcceptTcpClient(asyncResult));
ThreadPool.QueueUserWorkItem((object state) => handler.Process());
listenerSocket.BeginAcceptTcpClient(new AsyncCallback(AcceptClient), null);
}
}
private static bool shutdown = false;
internal static void Stop()
{
shutdown = true;
listenerSocket.Stop();
}
Run Code Online (Sandbox Code Playgroud)
更新2 …
在.NET框架中,有一个类TcpClient可以从电子邮件服务器中检索电子邮件.本TcpClient类有4个构造与内搭最多两个参数的服务器连接.它适用于那些不使用SSL的服务器.但是gmail或许多其他电子邮件提供商使用SSL进行IMAP.
我可以连接gmail服务器但无法使用email_id和密码进行身份验证.
我的验证用户代码是
public void AuthenticateUser(string username, string password)
{
_imapSw.WriteLine("$ LOGIN " + username + " " + password);
//_imapSw is a object of StreamWriter class
_imapSw.Flush();
Response();
}
Run Code Online (Sandbox Code Playgroud)
但是这段代码无法登录.
那么TcpClient当我必须使用SSL时,如何使用该类来检索电子邮件?
我知道TcpClient是套接字类的包装器,如果使用TcpClient,我可以访问底层套接字,但是包装器究竟做了什么?
当使用TCPClient时,我需要继续调用Receive(),就像我使用套接字一样,或者包装器是否确保我的所有数据都出现?
最后,我可以在服务器和客户端上使用TcpClient来包装套接字(在使用TcpListener接受服务器上的原始连接之后)
因此,启动终止的对等体 - 即首先调用close() - 将最终处于TIME_WAIT状态.[...]
但是,在服务器上处于TIME_WAIT状态的许多套接字可能会出现问题,因为它最终可能会阻止接受新连接.[...]
相反,请设计应用程序协议,以便始终从客户端启动连接终止.如果客户端总是知道它何时读取了所有剩余数据,则它可以启动终止序列.例如,浏览器在读取所有数据时可以从Content-Length HTTP标头中获知,并且可以启动关闭.(我知道在HTTP 1.1中它会保持打开一段时间以便重用,然后关闭它.)
我想使用TcpClient/TcpListener来实现它,但目前尚不清楚如何使其正常工作.
这是大多数MSDN示例所示的典型方式 - 双方调用Close(),而不仅仅是客户端:
private static void AcceptLoop()
{
listener.BeginAcceptTcpClient(ar =>
{
var tcpClient = listener.EndAcceptTcpClient(ar);
ThreadPool.QueueUserWorkItem(delegate
{
var stream = tcpClient.GetStream();
ReadSomeData(stream);
WriteSomeData(stream);
tcpClient.Close(); <---- note
});
AcceptLoop();
}, null);
}
private static void ExecuteClient()
{
using (var client = new TcpClient())
{
client.Connect("localhost", 8012);
using (var stream = client.GetStream())
{
WriteSomeData(stream);
ReadSomeData(stream);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我运行20个客户端之后,套装软件显示了很多插座的客户端和服务器都 …
基本上,我想向tcp服务器发出多个异步请求.我目前有一个只有同步的工作客户端,并在每次网络调用时阻止UI.由于多个请求几乎可能同时发生,我尝试这样做:
private object readonly readLock = new object();
public async Task UpdateDetailsAsync()
{
//I want every request to wait their turn before requesting (using the connection)
//to prevent a read call from catching any data from another request
lock (readLock)
{
Details details = await connection.GetDetailsAsync();
detailsListBox.Items = details;
}
}
Run Code Online (Sandbox Code Playgroud)
我确信这不是一个很好用的锁,但这是我能想到的唯一方法,可以让电话等待轮到他们.有没有我可以用来实现这种行为的对象?我认为Monitor会是一样的所以我没有尝试(我知道他们是多线程的东西,但这就是我所熟悉的......)
我想运行一组通常在telnet中运行的命令(来自c#).
例如,我想运行以下内容
using System;
using System.Diagnostics;
namespace InteractWithConsoleApp
{
class Program
{
static void Main(string[] args)
{
ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
cmdStartInfo.FileName = @"C:\Windows\System32\cmd.exe";
cmdStartInfo.RedirectStandardOutput = true;
cmdStartInfo.RedirectStandardError = true;
cmdStartInfo.RedirectStandardInput = true;
cmdStartInfo.UseShellExecute = false;
cmdStartInfo.CreateNoWindow = true;
Process cmdProcess = new Process();
cmdProcess.StartInfo = cmdStartInfo;
cmdProcess.ErrorDataReceived += cmd_Error;
cmdProcess.OutputDataReceived += cmd_DataReceived;
cmdProcess.EnableRaisingEvents = true;
cmdProcess.Start();
cmdProcess.BeginOutputReadLine();
cmdProcess.BeginErrorReadLine();
cmdProcess.StandardInput.WriteLine("telnet telehack.com");
int milliseconds = 2000;
System.Threading.Thread.Sleep(milliseconds);
cmdProcess.StandardInput.WriteLine("exit");
cmdProcess.StandardInput.WriteLine("exit");
cmdProcess.WaitForExit();
}
static void cmd_DataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data);
} …Run Code Online (Sandbox Code Playgroud) 当我运行以下代码时:
struct sockaddr_in sin;
int addrlen;
addrlen=sizeof(sin);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr=inet_addr("123.456.789.112");
sin.sin_port=htons(0); // so that the kernel reserves a unique port for us
sd_server = socket(PF_INET, SOCK_STREAM, 0);
bind(sd_server, (struct sockaddr *) &sin, sizeof(sin));
getsockname(sd_server,(struct sockaddr*)&sin,&addrlen);
port=ntohs(sin.sin_port);
printf("port number = %d\n",port);
Run Code Online (Sandbox Code Playgroud)
根据套接字,我必须得到1024到5000之间的端口号,但是我的端口号大约是30,000.
我该怎么办?
就像标题说的那样:
TcpClient如何实现IDisposable并且没有公共Dispose方法?
我正在使用NetworkStream和TcpClient使用BeginRead异步接收数据.我需要对此操作应用超时,以便在指定的时间后读取将被中止.
据我所知,NetworkStream或TcpClient不支持 - 有一个ReceiveTimeout属性,但这似乎只适用于同步等效 - 'Read'.
甚至底层的Socket类似乎也不支持其BeginReceive方法中的超时.
我已经搜索过这个问题,我看到的唯一建议的解决方案是设置另一个后台线程来取消操作,如果它在超时期限内没有完成.这看起来像是一个可怕的黑客.当然有更好的方法吗?
我正在阅读有关TcpClient.Close()的文档并注意到这一点:
调用此方法最终将导致关联的Socket关闭,并且还将关闭用于发送和接收数据的关联NetworkStream(如果已创建).
因此,纠正我,如果我错了,但是这说,如果一个调用Close()的TcpClient是,NetworkStream也将被关闭.
那么为什么在代码示例的末尾都会Close()被调用?
networkStream.Close();
tcpClient.Close();
Run Code Online (Sandbox Code Playgroud)
只打电话会一样tcpClient.Close();好吗?
tcpclient ×10
c# ×6
sockets ×4
.net ×3
tcplistener ×2
async-await ×1
asynchronous ×1
beginread ×1
beginreceive ×1
dispose ×1
email ×1
idisposable ×1
kernel ×1
telnet ×1