我一直在关注一个制作聊天程序的旧教程,并且我一直在对其进行剖析以适应新形式,尽管我已经让它按预期工作,但它遇到了错误:“无法从传输中读取数据连接:阻塞操作被 WSACancelBlockingCall 调用中断。”
指向这部分代码。
while (Connected)
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
我只有在关闭客户端或断开连接时才会收到错误消息。
这是大部分客户端代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace Table_Top_RPG
{
public partial class Connect : Form
{
// Will hold the user name
private string UserName = "Unknown";
public static StreamWriter swSender;
private StreamReader srReceiver;
private TcpClient tcpServer;
// Needed to update the form with messages from another thread
private delegate void UpdateLogCallback(string strMessage);
// Needed to set the form to a "disconnected" state from another thread
private delegate void CloseConnectionCallback(string strReason);
private Thread thrMessaging;
private IPAddress ipAddr;
private bool Connected;
public Connect()
{
// On application exit, don't forget to disconnect first
Application.ApplicationExit += new EventHandler(OnApplicationExit);
InitializeComponent();
}
private void BtnConnect_Click(object sender, EventArgs e)
{
// If we are not currently connected but awaiting to connect
if (Connected == false)
{
InitializeConnection();
}
else // We are connected, thus disconnect
{
CloseConnection("Disconnected at user's request.");
}
}
// The event handler for application exit
public void OnApplicationExit(object sender, EventArgs e)
{
if (Connected == true)
{
// Closes the connections, streams, etc.
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
}
private void InitializeConnection()
{
// Parse the IP address from the TextBox into an IPAddress object
ipAddr = IPAddress.Parse(Connect.IpBox.Text);
// Start a new TCP connections to the chat server
tcpServer = new TcpClient();
tcpServer.Connect(ipAddr, int.Parse(Connect.PortBox.Text));
// Helps us track whether we're connected or not
Connected = true;
// Prepare the form
UserName = Connect.NameBox.Text;
// Disable and enable the appropriate fields
IpBox.Enabled = false;
NameBox.Enabled = false;
Main.TxtMsg.Enabled = true;
Connect.BtnConnect.Text = "Disconnect";
// Send the desired username to the server
swSender = new StreamWriter(tcpServer.GetStream());
swSender.WriteLine(UserName);
swSender.Flush();
// Start the thread for receiving messages and further communication
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
private void ReceiveMessages()
{
// Receive the response from the server
srReceiver = new StreamReader(tcpServer.GetStream());
// If the first character of the response is 1, connection was successful
string ConResponse = srReceiver.ReadLine();
// If the first character is a 1, connection was successful
if (ConResponse[0] == '1')
{
// Update the form to tell it we are now connected
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { "Connected Successfully!" });
}
else // If the first character is not a 1 (probably a 0), the connection was unsuccessful
{
string Reason = "Not Connected: ";
// Extract the reason out of the response message. The reason starts at the 3rd character
Reason += ConResponse.Substring(2, ConResponse.Length - 2);
// Update the form with the reason why we couldn't connect
this.Invoke(new CloseConnectionCallback(this.CloseConnection), new object[] { Reason });
// Exit the method
return;
}
// While we are successfully connected, read incoming lines from the server
while (Connected)
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
}
internal void CloseConnection(string Reason)
{
// Show the reason why the connection is ending
Main.ChatLog.AppendText(Reason + "\r\n");
// Enable and disable the appropriate controls on the form
IpBox.Enabled = true;
NameBox.Enabled = true;
Main.TxtMsg.Enabled = false;
BtnConnect.Text = "Connect";
// Close the objects
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
// This method is called from a different thread in order to update the log TextBox
private void UpdateLog(string strMessage)
{
// Append text also scrolls the TextBox to the bottom each time
Main.ChatLog.AppendText(strMessage + "\r\n");
}
}
}
还有另一种称为 Main 的表单,其中发送了所有聊天对话框,但其大部分代码不相关。
如果有人知道更好的方法来处理这个问题或者知道一个好的聊天程序教程,我可以通过更好的例子来了解如何正确处理客户端连接和断开连接而不会崩溃,我将不胜感激。