नीचे एक सी # कार्यक्रम समस्या का प्रदर्शन है।सॉकेट क्यों है। टाइमआउट को अनंत पर सेट होने पर आधा बंद कनेक्शन पर समय-समय पर रिसीव करें?
सर्वर सॉकेट पर सुनना शुरू कर देता है। क्लाइंट सर्वर से जुड़ता है, एक संदेश भेजता है, कनेक्शन के आधे हिस्से को बंद करने के लिए शट डाउन (सॉकेटशूटडाउन.एंड) का उपयोग करता है ताकि सर्वर को पता चल सके कि संदेश का अंत कहां है, और सर्वर से प्रतिक्रिया के लिए इंतजार कर रहा है। सर्वर संदेश पढ़ता है, कुछ लंबा गणना (नींद कॉल के साथ यहां अनुकरण) करता है, क्लाइंट को एक संदेश भेजता है, और कनेक्शन बंद कर देता है।
विंडोज़ पर, क्लाइंट का रिसीव कॉल हमेशा 2 मिनट के बाद विफल रहता है "एक कनेक्शन प्रयास विफल हुआ क्योंकि कनेक्टेड पार्टी ने समय के बाद ठीक से जवाब नहीं दिया था, या स्थापित कनेक्शन विफल हुआ क्योंकि कनेक्टेड होस्ट जवाब देने में विफल रहा है" यहां तक कि हालांकि टाइमआउट अनंत पर सेट है।
यदि मैं लिनक्स में मोनो के साथ प्रोग्राम चलाता हूं, तो टाइमआउट नहीं होता है, भले ही मैं "लंबा ऑपरेशन" 10 मिनट तक सेट करता हूं, लेकिन यह विंडोज में होता है चाहे मैं इसे मोनो या .NET के साथ चलाता हूं। यदि मैं टाइमआउट को 1 सेकंड पर सेट करता हूं, तो यह 1 सेकंड के बाद समाप्त हो जाता है। दूसरे शब्दों में, यह निर्धारित समय या 2 मिनट में जो भी हो, जो भी कम हो।
एक समान नमूना प्रोग्राम जिसमें सर्वर क्लाइंट को संदेश भेजता है, क्लाइंट से सर्वर तक कोई संदेश नहीं है और कोई आधा नज़दीक नहीं है, बिना किसी टाइमआउट के अपेक्षित कार्य करता है।
कोई संदेश पूरा होने पर सर्वर को इंगित करने के कुछ अन्य तरीकों का उपयोग करने के लिए मैं अपने प्रोटोकॉल को संशोधित करके इसे प्राप्त कर सकता हूं (शायद संदेश की लंबाई के साथ संदेश को उपसर्ग करना)। लेकिन मैं जानना चाहता हूं कि यहां क्या हो रहा है। सॉकेट क्यों होता है। टाइमआउट को अनंत पर सेट होने पर आधा बंद कनेक्शन पर समय निकाल दें?
जो मैं समझता हूं उससे, केवल उसके आधा बंद भेजने वाला कनेक्शन अनिश्चित काल तक डेटा प्राप्त करना जारी रखने में सक्षम होना चाहिए। ऐसा लगता है कि विंडोज के इस तरह के मौलिक हिस्से में एक बग होगा। क्या मुझसे कुछ गलत हो रही है?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// Start server thread
Thread serverThread = new Thread(ServerStart);
serverThread.IsBackground = true;
serverThread.Start();
// Give the server some time to start listening
Thread.Sleep(2000);
ClientStart();
}
static int PortNumber = 8181;
static void ServerStart()
{
TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Any, PortNumber));
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
Task connectionHandlerTask = new Task(ConnectionEntryPoint, client);
connectionHandlerTask.Start();
}
listener.Stop();
}
static void ConnectionEntryPoint(object clientObj)
{
using (TcpClient client = (TcpClient)clientObj)
using (NetworkStream stream = client.GetStream())
{
// Read from client until client closes its send half.
byte[] requestBytes = new byte[65536];
int bufferPos = 0;
int lastReadSize = -1;
while (lastReadSize != 0)
{
lastReadSize = stream.Read(requestBytes, bufferPos, 65536 - bufferPos);
bufferPos += lastReadSize;
}
client.Client.Shutdown(SocketShutdown.Receive);
string message = Encoding.UTF8.GetString(requestBytes, 0, bufferPos);
// Sleep for 2 minutes, 30 seconds to simulate a long-running calculation, then echo the client's message back
byte[] responseBytes = Encoding.UTF8.GetBytes(message);
Console.WriteLine("Waiting 2 minutes 30 seconds.");
Thread.Sleep(150000);
try
{
stream.Write(responseBytes, 0, responseBytes.Length);
}
catch (SocketException ex)
{
Console.WriteLine("Socket exception in server: {0}", ex.Message);
}
}
}
static void ClientStart()
{
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
// Set receive timeout to infinite.
socket.ReceiveTimeout = -1;
// Connect to server
socket.Connect(IPAddress.Loopback, PortNumber);
// Send a message to the server, then close the send half of the client's connection
// to let the server know it has the entire message.
string requestMessage = "Hello";
byte[] requestBytes = Encoding.UTF8.GetBytes(requestMessage);
socket.Send(requestBytes);
socket.Shutdown(SocketShutdown.Send);
// Read the server's response. The response is done when the server closes the connection.
byte[] responseBytes = new byte[65536];
int bufferPos = 0;
int lastReadSize = -1;
Stopwatch timer = Stopwatch.StartNew();
try
{
while (lastReadSize != 0)
{
lastReadSize = socket.Receive(responseBytes, bufferPos, 65536 - bufferPos, SocketFlags.None);
bufferPos += lastReadSize;
}
string responseMessage = Encoding.UTF8.GetString(responseBytes, 0, bufferPos);
Console.WriteLine(responseMessage);
}
catch (SocketException ex)
{
// Timeout always occurs after 2 minutes. Why?
timer.Stop();
Console.WriteLine("Socket exception in client after {0}: {1}", timer.Elapsed, ex.Message);
}
}
}
}
}
निम्नलिखित कार्यक्रम नहीं बल्कि संदेश के अंत का संकेत करने के लिए socket.Shutdown (SocketShutdown.Send) का उपयोग करने से एक 4-बाइट संदेश लंबाई के साथ संदेश उपसर्ग। टाइमआउट इस कार्यक्रम में नहीं होता है।
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
namespace WithoutShutdown
{
class Program
{
static void Main(string[] args)
{
// Start server thread
Thread serverThread = new Thread(ServerStart);
serverThread.IsBackground = true;
serverThread.Start();
// Give the server some time to start listening
Thread.Sleep(2000);
ClientStart();
}
static int PortNumber = 8181;
static void ServerStart()
{
TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Any, PortNumber));
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
Task connectionHandlerTask = new Task(ConnectionEntryPoint, client);
connectionHandlerTask.Start();
}
listener.Stop();
}
static void SendMessage(Socket socket, byte[] message)
{
// Send a 4-byte message length followed by the message itself
int messageLength = message.Length;
byte[] messageLengthBytes = BitConverter.GetBytes(messageLength);
socket.Send(messageLengthBytes);
socket.Send(message);
}
static byte[] ReceiveMessage(Socket socket)
{
// Read 4-byte message length from the client
byte[] messageLengthBytes = new byte[4];
int bufferPos = 0;
int lastReadSize = -1;
while (bufferPos < 4)
{
lastReadSize = socket.Receive(messageLengthBytes, bufferPos, 4 - bufferPos, SocketFlags.None);
bufferPos += lastReadSize;
}
int messageLength = BitConverter.ToInt32(messageLengthBytes, 0);
// Read the message
byte[] messageBytes = new byte[messageLength];
bufferPos = 0;
lastReadSize = -1;
while (bufferPos < messageLength)
{
lastReadSize = socket.Receive(messageBytes, bufferPos, messageLength - bufferPos, SocketFlags.None);
bufferPos += lastReadSize;
}
return messageBytes;
}
static void ConnectionEntryPoint(object clientObj)
{
using (TcpClient client = (TcpClient)clientObj)
{
byte[] requestBytes = ReceiveMessage(client.Client);
string message = Encoding.UTF8.GetString(requestBytes);
// Sleep for 2 minutes, 30 seconds to simulate a long-running calculation, then echo the client's message back
byte[] responseBytes = Encoding.UTF8.GetBytes(message);
Console.WriteLine("Waiting 2 minutes 30 seconds.");
Thread.Sleep(150000);
try
{
SendMessage(client.Client, responseBytes);
}
catch (SocketException ex)
{
Console.WriteLine("Socket exception in server: {0}", ex.Message);
}
}
}
static void ClientStart()
{
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
// Set receive timeout to infinite.
socket.ReceiveTimeout = -1;
// Connect to server
socket.Connect(IPAddress.Loopback, PortNumber);
// Send a message to the server
string requestMessage = "Hello";
byte[] requestBytes = Encoding.UTF8.GetBytes(requestMessage);
SendMessage(socket, requestBytes);
// Read the server's response.
Stopwatch timer = Stopwatch.StartNew();
try
{
byte[] responseBytes = ReceiveMessage(socket);
string responseMessage = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseMessage);
}
catch (SocketException ex)
{
// Timeout does not occur in this program because it does not call socket.Shutdown(SocketShutdown.Send)
timer.Stop();
Console.WriteLine("Socket exception in client after {0}: {1}", timer.Elapsed, ex.Message);
}
}
}
}
}
के लिए उपहार क्या है? आपने अपने प्रश्न का उत्तर दिया है ना? – jeremy
हां, बक्षीस पोस्ट करने के बाद और कोई वास्तविक जवाब नहीं मिलने के कई दिन बाद। –