我正在尝试在 Winforms 中使用 C# 制作异步 TCP 服务器/客户端。我已经从控制台完成了,一切都很好。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void StartListener_Click(object sender, EventArgs e)
{
AsyncSocketListener.StartListener();
}
public class ObjectState {
public Socket socket = null;
public const int bufferSize = 1024;
public byte[] buffer = new byte[bufferSize];
public StringBuilder sb = new StringBuilder();
}
public class AsyncSocketListener {
public static ManualResetEvent completed = new ManualResetEvent(false);
public static void StartListener()
{
Form1 objects = new Form1();
byte[] bytes = new byte[1024];
int port = int.Parse(objects.ServerPort.Text);
IPAddress ip = IPAddress.Parse(objects.ServerIP.Text);
IPEndPoint ep = new IPEndPoint(ip, port);
Socket listener = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(ep);
listener.Listen(999999999);
while (true) {
completed.Reset();
MessageBox.Show("Listener started: Waiting for incoming connections", "Listener started", MessageBoxButtons.OK, MessageBoxIcon.Information);
listener.BeginAccept(new AsyncCallback(AcceptCallBack), listener);
}
}
catch (Exception a) {
MessageBox.Show(a.Message, "Error - Listener failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private static void AcceptCallBack(IAsyncResult ar) {
completed.Set();
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);
ObjectState state = new ObjectState();
state.socket = handler;
handler.BeginReceive(state.buffer, 0, ObjectState.bufferSize, 0, new AsyncCallback(ReadCallBack), state);
}
private static void ReadCallBack(IAsyncResult ar)
{
string content = String.Empty;
ObjectState state = (ObjectState) ar.AsyncState;
Socket handler = state.socket;
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
content = state.sb.ToString();
if (content.IndexOf("<EOF>", StringComparison.Ordinal) > -1)
{
MessageBox.Show($"Read: {content.Length} bytes from socket Data: {content}", "Socket data", MessageBoxButtons.OK, MessageBoxIcon.Information);
Send(handler, content);
}
else
{
handler.BeginReceive(state.buffer, 0, ObjectState.bufferSize, 0, new AsyncCallback(ReadCallBack), state);
}
}
}
private static void Send(Socket handler, String content)
{
byte[] byteData = Encoding.ASCII.GetBytes(content);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try {
Socket handler = (Socket) ar.AsyncState;
int byteSent = handler.EndSend(ar);
MessageBox.Show($"Sent: {byteSent} to client", "Socket data", MessageBoxButtons.OK, MessageBoxIcon.Information);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e) {
MessageBox.Show(e.Message, "Socket Callback Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
}
使用 GUI 执行此操作时,我的服务器出现问题。在我的
AsyncSocketListener
类中,StartListener
函数无法捕获 GUI 文本框中传递的值。
Form1 objects = new Form1();
byte[] bytes = new byte[1024];
int port = int.Parse(objects.ServerPort.Text);
IPAddress ip = IPAddress.Parse(objects.ServerIP.Text);
IPEndPoint ep = new IPEndPoint(ip, port);
知道这是怎么回事吗?为什么我无法从班级获取值?
我是 C# 新手,如果这是一个愚蠢的问题,我很抱歉。
因此,如果您查看此行的侦听器代码
Form1 objects = new Form1();
您正在创建一个全新的表单实例,然后尝试使用此处的值。
您需要将引用传递给原始表单。所以试试这个;
public class AsyncSocketListener
{
public static ManualResetEvent completed = new ManualResetEvent(false);
//Amend this to accept a reference to the Form1 object
public static void StartListener(Form1 objects)
{
//Rest of code as before
然后像这样传递引用;
private void StartListener_Click(object sender, EventArgs e)
{
AsyncSocketListener.StartListener(this);
}
也许您还可以采取其他一些措施来改进代码(请参阅注释),包括将“
objects
”重命名为更有意义的名称,例如“form
”。
事实上,最好将
Form1
与 Listener 类完全解耦,然后将值传递给侦听器,如下所示;
public static void StartListener(IPAddress ip, int port)
{
byte[] bytes = new byte[1024];
IPEndPoint ep = new IPEndPoint(ip, port);
//Rest of code as before
像这样传递引用;
private void StartListener_Click(object sender, EventArgs e)
{
AsyncSocketListener.StartListener(IPAddress.Parse(this.ServerIP.Text), int.Parse(this.ServerPort.Text));
}