Socket停止接收新数据
本文关键字:数据 新数据 Socket | 更新日期: 2023-09-27 18:06:33
在我开始解释我的问题之前,我必须说我在网络/套接字方面缺乏经验(可能是我遇到麻烦的原因的解释)
废话少说:
情况如下我有一个桌面WPF应用程序,它必须使用套接字从服务器接收不断的数据流。目前不需要发送任何数据,只需要接收部分。我目前有2个线程。第一个用于运行应用程序并进行任何GUI更新,第二个用于从套接字接收任何数据并通过委托将其传递给我的GUI线程。
由于某种原因,它第一次接收到数据,然后停止获取新数据,只输出第一次接收到的相同字符串。
下面的代码是MSDN的例子,稍微调整以适应我的需要。
// State object for receiving data from remote device.
public class StateObject {
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousClient {
// The port number for the remote device.
private const int port = 2003;
static Socket currentsocket;
static int packetsreceived = 0;
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false);
// The response from the remote device.
private static String response = String.Empty;
public static void StartClient() {
// Connect to a remote device.
try {
// Establish the remote endpoint for the socket.
// ip adress : xx.xx.xx.xxx
IPHostEntry ipHostInfo = Dns.GetHostEntry(IPAddress.Parse("xx.xx.xx.xxx"));
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
currentsocket = client;
// Send test data to the remote device.
//Send(client,"This is a test<EOF>");
//sendDone.WaitOne();
// Connect to the remote endpoint.
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
((MainWindow)Application.Current.MainWindow).socketconnected = true;
((MainWindow)Application.Current.MainWindow).loadingimage.Visibility = Visibility.Hidden;
((MainWindow)Application.Current.MainWindow).statuslabel.Content = "Connected";
((MainWindow)Application.Current.MainWindow).statuslabel.Foreground = System.Windows.Media.Brushes.Green;
}));
// Receive the responses from the remote device.
// main loop of receiving
while (true)
{
if (!client.Connected)
{
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
}
if (client.Connected)
{
Receive(client);
receiveDone.WaitOne();
packetsreceived++;
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
((MainWindow)Application.Current.MainWindow).packetslabel.Content = packetsreceived;
((MainWindow)Application.Current.MainWindow).panel.Text += response;
}));
Thread.Sleep(1000);
// Release the socket.
//client.Shutdown(SocketShutdown.Both);
//client.Close();
}
}
} catch (Exception e) {
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
((MainWindow)Application.Current.MainWindow).socketconnected = false;
((MainWindow)Application.Current.MainWindow).connectbutton.Content = "Connect";
((MainWindow)Application.Current.MainWindow).loadingimage.Visibility = Visibility.Hidden;
((MainWindow)Application.Current.MainWindow).statuslabel.Content = "Disconnected";
((MainWindow)Application.Current.MainWindow).statuslabel.Foreground = System.Windows.Media.Brushes.Red;
}));
}
}
private static void Receive(Socket client) {
try {
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback( IAsyncResult ar ) {
try {
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
new AsyncCallback(ReceiveCallback), state);
} else {
// All the data has arrived; put it in response.
if (state.sb.Length > 1) {
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set();
}
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartClient();
}
最后在我的主线程:
// starts the socket thread and starts recieving
private void connectbutton_Click(object sender, System.Windows.RoutedEventArgs e)
{
if (!socketconnected)
{
statuslabel.Content = "Connecting..";
loadingimage.Visibility = Visibility.Visible;
// socket stuff
socketThread = new Thread(new ThreadStart(() =>
{
AsynchronousClient.Main(new string[0]);
// Start the Dispatcher Processing
System.Windows.Threading.Dispatcher.Run();
}));
// Set the apartment state
socketThread.SetApartmentState(ApartmentState.STA);
// Make the thread a background thread
socketThread.IsBackground = true;
// Start the thread
socketThread.Start();
connectbutton.Content = "Disconnect";
}
else
{
socketThread.Abort();
socketconnected = false;
}
}
我找到了解决办法。代码工作正常,但是,有一个连接问题。
需要Thread.Sleep()来确保它正确连接到套接字。我通过调试这部分代码发现了这一点,并发现当我跳过代码时,它没有获得新数据,但是当我跳过所有代码时,它确实收到了新数据。
我是这样解决的:
// Connect to a remote device.
try {
// Establish the remote endpoint for the socket.
// ip adress : xx.xx.xx.xxx
IPHostEntry ipHostInfo = Dns.GetHostEntry(IPAddress.Parse("xx.xx.xx.xxx"));
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
currentsocket = client;
// Send test data to the remote device.
//Send(client,"This is a test<EOF>");
//sendDone.WaitOne();
// Connect to the remote endpoint.
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
Thread.sleep(250);
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
((MainWindow)Application.Current.MainWindow).socketconnected = true;
((MainWindow)Application.Current.MainWindow).loadingimage.Visibility = Visibility.Hidden;
((MainWindow)Application.Current.MainWindow).statuslabel.Content = "Connected";
((MainWindow)Application.Current.MainWindow).statuslabel.Foreground = System.Windows.Media.Brushes.Green;
}));