我们正在使用HttpURLConnection API来经常向同一个提供程序调用REST API(一种聚合用例).我们希望保持对提供者主机始终开放的5个连接池(始终是相同的IP).
什么是正确的解决方案?这是我们尝试的:
System.setProperty("http.maxConnections", 5); // set globally only once
...
// everytime we need a connection, we use the following
HttpURLConnection conn = (HttpURLConnection) (new URL(url)).openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setDoOutput(false);
conn.setUseCaches(true);
...
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
...
Run Code Online (Sandbox Code Playgroud)
此时我们读取输入流,直到BufferedReader不再返回字节为止.如果我们想要重用与提供者的底层连接,那么在那之后我们该怎么做?我们的印象是,如果完全读取输入流,则将连接添加回池中.
它以这种方式工作了几个星期,但今天它停止工作产生这个异常: java.net.SocketException: Too many open files
我们在CLOSE_WAIT状态下发现了许多套接字(通过运行lsof):
java 1814 root 97u IPv6 844702 TCP colinux:58517->123.123.254.205:www (CLOSE_WAIT)
conn.getInputStream().close()或conn.disconnect()是否会完全关闭连接并将其从池中删除?
使用.NET,TcpClient如果我BeginRead()在关联的网络流上调用异步,我仍然可以Write()在另一个线程上调用该流吗?
还是我要lock()的TcpClient代码被称为从后面BeginRead和不发送的代码?
如果我关闭了TcpClient:
client.GetStream().Close();
client.Close();
Run Code Online (Sandbox Code Playgroud)
我一定要lock()上TcpClient呢?
我连接到代理,并使用connect命令发送一些自定义标头.这是一项要求.我收到200回复.然后我尝试使用相同的连接来执行get请求(搜索附加代码为"GET {0}")但我总是得到一个错误,最终"连接关闭"(无法回想起确切的错误).从根本上说,我需要通过像https:\ www.somesecuresite.com这样的网站来访问代码.某些部分被排除在外.
using (TcpClient client = new TcpClient(proxy, proxyPort))
{
using (NetworkStream stream = client.GetStream())
{
string EncodedData = encodeUIDPWD(UserName, Password);
#region Establish Tcp tunnel
string reqString = "CONNECT {0}:{1} HTTP/1.1\r\nProxy-Authorization:Basic " + EncodedData + "\r\nHost: {2}:{3}\r\n";
reqString += "Proxy-Connection: keep-alive\r\n";
reqString += "Connection: keep-alive\r\n";
reqString += "Header1: " + header1 + "\r\n";
reqString += "Header2: " + header2 + "\r\n";
reqString += "None: " + None + "\r\n\r\n";
string rString = String.Format(reqString, myUri.Host, myUri.Port, myUri.Host, myUri.Port);
#endregion
ServicePointManager.SecurityProtocol …Run Code Online (Sandbox Code Playgroud) 我被要求将使用的bash脚本转换nc -z为PowerShell。
该站点告诉我nc -z测试端口是否“未连接”打开。有什么方法可以使用.Net做到这一点?
通常,要测试端口是否打开,我会用.Net TcpClient创建一个连接。如果连接成功,我也会报告所有问题。MVE:
$isConnected = $false
$client = New-Object -TypeName 'System.Net.Sockets.TcpClient'
try {
$client.Connect($host, $port)
$isConnected = $client.Connected
$client.GetStream().Close(); # handle bug in .net 1.1
$client.Close();
} catch {
$isConnected = $false
} finally {
if ($client.Dispose) {$client.Dispose()} # dispose method not available in all versions, so check before calling
}
Run Code Online (Sandbox Code Playgroud)
但是,尽管不发送任何数据,但它确实可以连接。
可能是由于的描述具有nc -z误导性/只是意味着没有发送数据...我无法以任何方式找到确认。
我正在构建一个简单的代理,它将记录通过它传递的某些请求。代理不需要干扰通过它的流量(在项目的这一点上),因此我尝试在处理过程中尽可能少地解析原始请求/响应(请求和响应被推送)到要在代理外部记录的队列)。
我的示例工作正常,但无法可靠地判断“响应”何时完成,因此我的连接保持打开状态的时间超过了所需的时间。相关代码如下:
var request = getRequest(url);
byte[] buffer;
int bytesRead = 1;
var dataSent = false;
var timeoutTicks = DateTime.Now.AddMinutes(1).Ticks;
Console.WriteLine(" Sending data to address: {0}", url);
Console.WriteLine(" Waiting for response from host...");
using (var outboundStream = request.GetStream()) {
while (request.Connected && (DateTime.Now.Ticks < timeoutTicks)) {
while (outboundStream.DataAvailable) {
dataSent = true;
buffer = new byte[OUTPUT_BUFFER_SIZE];
bytesRead = outboundStream.Read(buffer, 0, OUTPUT_BUFFER_SIZE);
if (bytesRead > 0) { _clientSocket.Send(buffer, bytesRead, SocketFlags.None); }
Console.WriteLine(" pushed {0} bytes to requesting host...", _backBuffer.Length);
}
if …Run Code Online (Sandbox Code Playgroud) 我试图获得有关以比HttpWebRequest和HttpWebResponse更低的权限连接到更低级别网站的信息。我正在使用C#。
我希望能够看到有关dns查找以及建立连接所花费的时间的信息(如果建立了新的连接)。HttpWebRequest和HttpWebResponse的工作级别高于此级别,我想问一下是否有一种获取底层TcpClient对象(或它们使用的任何低级对象)的方法。
如果不可能,那么有没有办法获取和操纵.net所维护的连接列表,而无需通过HttpWebRequest或HttpWebResponse获取它?
我不能更改正在使用TcpClient的应用程序,因为要可靠地实现所有http东西会很费时间。
我正在阅读这篇文章,并在解决方案中注意到,如果您发送与实际数据分开的数据长度,Nagle 的算法可能会发挥作用并使发送的数据不同步。
我想知道这一点,因为我看到很多代码示例客户端首先发送数据的长度,然后发送数据本身以进行单独的调用。这个问题对他们没有影响吗?
我是否应该将数据的长度和数据本身连接到一个字节数组中并一次性发送?如果是这样,是否有一种更好的方法来连接两个字节数组,而无需手动将两个(循环)中的所有数据复制到新数组中?对于经常发生的事情(每次用户或服务器在彼此之间发送数据时)来说,似乎效率很低。
我正在编写一个应用程序,需要通过tcp进行数百个套接字连接才能读/写数据.
我在这里遇到过这段代码片段,我想知道如何让它更强大.
这是我目前调用代码的方式:
foreach (var ip in listofIps)
{
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ip), 4001);
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
client.Connect(remoteEP);
await ReadAsync(client);
}
Run Code Online (Sandbox Code Playgroud)
以上是否有任何问题,如何进行优化以使其同时运行?
在代码片段中,缓冲区大小设置为1000.正如一个简单的说明,如果我只尝试打印出接收的字节,而不是剩余的0x00,我必须做这样的事情:
while (true)
{
await s.ReceiveAsync(awaitable);
int bytesRead = args.BytesTransferred;
if (bytesRead <= 0) break;
var hex = new StringBuilder(bytesRead * 2);
var msg = new byte[bytesRead];
for (int i = 0; i < bytesRead; i++)
msg[i] = args.Buffer[i];
foreach (byte b in msg)
hex.AppendFormat("{0:x2} ", b);
AppendLog(string.Format("RX: {0}", hex));
} …Run Code Online (Sandbox Code Playgroud)当我试图避免使用Thread.sleep(400)
我的代码时遇到问题,如下所示:
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
clientSocket = Connect(IP, Port);
Thread.Sleep(400);
NetworkStream networkStream = clientSocket.GetStream();
Send(networkStream, "My Data To send");
networkStream.Flush();
Run Code Online (Sandbox Code Playgroud)
和我的 send() 方法:
public static void Send(NetworkStream networkStream, string Data)
{
int range = 1000;
int datalength = 0;
foreach (string data in Enumerable.Range(0, Data.Length / range).Select(i => Data.Substring(i * range, range)))
{
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(data);
networkStream.Write(outStream, 0, outStream.Length);
datalength = datalength + range;
Thread.Sleep(50);
}
byte[] LastoutStream = System.Text.Encoding.ASCII.GetBytes(Data.Substring(datalength, Data.Length - datalength) + "$EOS$\r\n");
networkStream.Write(LastoutStream, …Run Code Online (Sandbox Code Playgroud) 我正在使用 nmodbus 库(从 Google 代码下载)通过 TCP 进行 modbus rtu 通信。
我正在使用硬件(RS485 到以太网转换器)将我的 modbus over RTU 请求转换为 TCP,反之亦然。
如果我发送请求并且 modbus 设备处于活动状态,则一切正常,但是如果我发送请求并且 modbus 设备未处于活动状态,则我的 tcpclient 连接会自动关闭,我希望它保持打开状态并抛出超时异常,但这没有发生。
我已经正确设置了超时值,但仍然没有结果。
我的示例伪代码如下
using (TcpClient _client = new TcpClient(ipAdd, 1025))
{
_client.NoDelay = true;
ModbusSerialMaster _device = ModbusSerialMaster.CreateRtu(tcpObj);
_device.Transport.ReadTimeout = 1000;
_device.Transport.WriteTimeout = 1000;
_device.ReadInputRegisters(meterID, startAdd, register);
}
Run Code Online (Sandbox Code Playgroud)
我已经使用modbus模拟器(Pollscan,modbus poll)验证了转换器和modbus硬件的功能
我相信我在设置 tcpclient 的属性时犯了一些错误,但不确定到底是什么。
任何建议、意见都非常值得赞赏。
tcpclient ×10
c# ×8
.net ×3
sockets ×3
http ×2
async-await ×1
asynchronous ×1
java ×1
modbus ×1
powershell ×1
servlets ×1
sleep ×1