我正在尝试一个关于Socket连接的基本项目。我创建了以下表单:
任务很简单。我将从左边发送消息,然后从右边接收。
我的代码如下:
private bool _senderStarted = false;
private bool _listenerStarted = false;
private Socket sListener;
private ManualResetEvent listenerNotifier = new ManualResetEvent(false);
private Socket sSender;
private IPEndPoint senderEndpoint = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Create sockets
sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sSender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
private void btnSenderStart_Click(object sender, EventArgs e)
{
_senderStarted = true;
btnSenderStart.Enabled = false;
btnSenderStop.Enabled = true;
txtMessage.Enabled = true;
btnSend.Enabled = true;
txtMessage.Clear();
txtMessage.Focus();
lstSender.Items.Clear();
// Create sender endpoint
string[] arr = txtSenderIP.Text.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
byte[] ips = arr.Select(x => byte.Parse(x)).ToArray();
IPAddress senderAddress = new IPAddress(ips);
senderEndpoint = new IPEndPoint(senderAddress, (int)txtSenderPort.Value);
sSender.Connect(senderEndpoint);
}
private void btnListenerStart_Click(object sender, EventArgs e)
{
_listenerStarted = true;
btnListenerStart.Enabled = false;
btnListenerStop.Enabled = true;
lstListener.Items.Clear();
// Create listener endpoint
string[] arr = txtListenerIP.Text.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
byte[] ips = arr.Select(x => byte.Parse(x)).ToArray();
IPAddress listenerAddress = new IPAddress(ips);
IPEndPoint listenerEndpoint = new IPEndPoint(listenerAddress, (int)txtSenderPort.Value);
// Bind listener to endpoint
sListener.Bind(listenerEndpoint);
bwListener.RunWorkerAsync();
}
private void btnSenderStop_Click(object sender, EventArgs e)
{
_senderStarted = false;
btnSenderStart.Enabled = true;
btnSenderStop.Enabled = false;
txtMessage.Enabled = false;
btnSend.Enabled = false;
txtMessage.Clear();
}
private void btnListenerStop_Click(object sender, EventArgs e)
{
_listenerStarted = false;
btnListenerStart.Enabled = true;
btnListenerStop.Enabled = false;
}
#region Listener
private void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
listenerNotifier.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject listenerState = new StateObject();
listenerState.workSocket = handler;
handler.BeginReceive(listenerState.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), listenerState);
}
public void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.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));
// Check for end-of-file tag. If it is not there, read more data.
content = state.sb.ToString();
this.Invoke(new MethodInvoker(delegate()
{
lstListener.Items.Add(content);
}));
}
}
#endregion
private void btnSend_Click(object sender, EventArgs e)
{
byte[] byteData = Encoding.ASCII.GetBytes(txtMessage.Text);
sSender.Send(byteData);
txtMessage.Clear();
txtMessage.Focus();
}
private void bwListener_DoWork(object sender, DoWorkEventArgs e)
{
sListener.Listen(10);
while (_listenerStarted)
{
// Set the event to nonsignaled state.
listenerNotifier.Reset();
// Start an asynchronous socket to listen for connections.
sListener.BeginAccept(new AsyncCallback(AcceptCallback), sListener);
// Wait until a connection is made before continuing.
listenerNotifier.WaitOne();
}
}
我可以成功发送一个mesasage,如图所示。但是当我尝试发送第二条消息时,它似乎发送消息监听器根本没有收到任何消息。我错过了什么,或者我应该修复什么?
问候。
答案 0 :(得分:1)
您没有启动后续接收操作。第一个完成后,您的代码不会尝试接收更多数据。如果在完成给定的接收操作处理后再次调用BeginReceive()
,则应该成功读取更多数据。
例如:
public void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.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));
// Check for end-of-file tag. If it is not there, read more data.
content = state.sb.ToString();
this.Invoke(new MethodInvoker(delegate()
{
lstListener.Items.Add(content);
}));
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
}
(顺便说一句:我最近看到过一些问题,它们遵循与您正在使用的代码类似的风格 - 命名约定,类设计,逻辑流程等 - 这让我相信这些是所有这些都是从一个常见的代码示例派生而来的。不幸的是,它并不是一个很好的网络I / O实现。我希望我知道这些例子的来源......在上下文中看到原始代码示例会很高兴。 / em>的