问题1:在我的客户端关闭后,服务器怎么也关闭了;
问题2:如果服务器要连接多个客户端,我想在AcceptCallback里继续调用Socket.BeginAccpet为什么不可以呢?如何才能连接多个客户端?代码如下:
【服务器端】using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;namespace AsyncTcpServer { public partial class Form1 : Form {
public const int BUFFSIZE = 1024;
public Socket m_server;
public byte[] m_buffer = new byte[BUFFSIZE]; // Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false); public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
//从程序设计上来说,只有创建界面的主线程才能访问界面上的控件
//因为我们在OnReceive中访问了控件,所以这里设置成false
CheckForIllegalCrossThreadCalls = false;
// Create a TCP/IP socket.
m_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 9998); try {
m_server.Bind(localEndPoint);
m_server.Listen(100); //while (true)
//{
// allDone.Reset();
m_server.BeginAccept(
new AsyncCallback(AcceptCallback),
m_server);
// allDone.WaitOne();
//}
} catch (Exception ex) {
MessageBox.Show(ex.ToString());
}
} public void AcceptCallback(IAsyncResult ar) {
try {
//allDone.Set();
// Get the socket that handles the client request.
//Socket listener = (Socket)ar.AsyncState;
Socket handler = m_server.EndAccept(ar); //返回的是什么?服务器的socket???? m_server = handler; handler.BeginReceive(m_buffer, 0, m_buffer.Length, 0,
new AsyncCallback(ReceiveCallback), handler);
} catch (Exception ex) {
m_server.BeginAccept(new AsyncCallback(AcceptCallback), m_server);
} } public void ReceiveCallback(IAsyncResult ar) {
String content = String.Empty;
// Read data from the client socket.
int bytesRead = m_server.EndReceive(ar);
string strData = Encoding.ASCII.GetString(m_buffer, 0, bytesRead);
try {
if (bytesRead > 0) {
if (strData.Equals("closeClient")) {
strData = "client has gotten out...";
}
lstContent.Items.Add(strData);
}
m_server.BeginReceive(m_buffer, 0, m_buffer.Length, 0,
new AsyncCallback(ReceiveCallback), m_server);
} catch (Exception ex) {
//MessageBox.Show(ex.ToString());
m_server.BeginAccept(new AsyncCallback(AcceptCallback), m_server);
}
} private void Send(String data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device.
m_server.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), m_server);
} private void SendCallback(IAsyncResult ar) {
try {
// Complete sending the data to the remote device.
int bytesSent = m_server.EndSend(ar); //handler.Shutdown(SocketShutdown.Both);
//handler.Close(); } catch (Exception e) {
MessageBox.Show(e.ToString());
}
}
}
}【客户端】
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using System.Net.Sockets;namespace AsyncTcpClient
{
public partial class Form1 : Form
{
public Socket m_client;
public EndPoint m_epServer;
public byte[] m_buffer;
public int port = 9998;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
m_epServer = new IPEndPoint(ipAddress, port);
m_client = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
m_client.BeginConnect(m_epServer,
new AsyncCallback(ConnectCallback), m_client);
}
catch (Exception ex)
{ }
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
// Complete the connection.
m_client.EndConnect(ar); lstContent.Items.Add("Socket connected to "+
m_client.RemoteEndPoint.ToString());
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
} private void Receive()
{
try
{
// Begin receiving the data from the remote device.
m_client.BeginReceive(m_buffer, 0, m_buffer.Length, 0,
new AsyncCallback(ReceiveCallback), m_client);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
} private void ReceiveCallback(IAsyncResult ar)
{
try
{
// Read data from the remote device.
int bytesRead = m_client.EndReceive(ar); if (bytesRead > 0)
{
lstContent.Items.Add(Encoding.ASCII.GetString(m_buffer, 0, bytesRead));
}
m_client.BeginReceive(m_buffer, 0, m_buffer.Length, 0,
new AsyncCallback(ReceiveCallback), m_client);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
} private void Send(String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device.
m_client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), m_client);
} private void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState; // Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
lstContent.Items.Add(String.Format("Sent {0} bytes to server.", bytesSent));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
} private void btnSend_Click(object sender, EventArgs e)
{
if (txtMessage.Text != string.Empty)
{
Send(txtMessage.Text);
}
} private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Send("closeClient");//发送关闭客户端指令
}
}
}
C# Tcp 异步 Socket 断开
问题2:如果服务器要连接多个客户端,我想在AcceptCallback里继续调用Socket.BeginAccpet为什么不可以呢?如何才能连接多个客户端?代码如下:
【服务器端】using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;namespace AsyncTcpServer { public partial class Form1 : Form {
public const int BUFFSIZE = 1024;
public Socket m_server;
public byte[] m_buffer = new byte[BUFFSIZE]; // Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false); public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
//从程序设计上来说,只有创建界面的主线程才能访问界面上的控件
//因为我们在OnReceive中访问了控件,所以这里设置成false
CheckForIllegalCrossThreadCalls = false;
// Create a TCP/IP socket.
m_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 9998); try {
m_server.Bind(localEndPoint);
m_server.Listen(100); //while (true)
//{
// allDone.Reset();
m_server.BeginAccept(
new AsyncCallback(AcceptCallback),
m_server);
// allDone.WaitOne();
//}
} catch (Exception ex) {
MessageBox.Show(ex.ToString());
}
} public void AcceptCallback(IAsyncResult ar) {
try {
//allDone.Set();
// Get the socket that handles the client request.
//Socket listener = (Socket)ar.AsyncState;
Socket handler = m_server.EndAccept(ar); //返回的是什么?服务器的socket???? m_server = handler; handler.BeginReceive(m_buffer, 0, m_buffer.Length, 0,
new AsyncCallback(ReceiveCallback), handler);
} catch (Exception ex) {
m_server.BeginAccept(new AsyncCallback(AcceptCallback), m_server);
} } public void ReceiveCallback(IAsyncResult ar) {
String content = String.Empty;
// Read data from the client socket.
int bytesRead = m_server.EndReceive(ar);
string strData = Encoding.ASCII.GetString(m_buffer, 0, bytesRead);
try {
if (bytesRead > 0) {
if (strData.Equals("closeClient")) {
strData = "client has gotten out...";
}
lstContent.Items.Add(strData);
}
m_server.BeginReceive(m_buffer, 0, m_buffer.Length, 0,
new AsyncCallback(ReceiveCallback), m_server);
} catch (Exception ex) {
//MessageBox.Show(ex.ToString());
m_server.BeginAccept(new AsyncCallback(AcceptCallback), m_server);
}
} private void Send(String data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device.
m_server.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), m_server);
} private void SendCallback(IAsyncResult ar) {
try {
// Complete sending the data to the remote device.
int bytesSent = m_server.EndSend(ar); //handler.Shutdown(SocketShutdown.Both);
//handler.Close(); } catch (Exception e) {
MessageBox.Show(e.ToString());
}
}
}
}【客户端】
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using System.Net.Sockets;namespace AsyncTcpClient
{
public partial class Form1 : Form
{
public Socket m_client;
public EndPoint m_epServer;
public byte[] m_buffer;
public int port = 9998;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
m_epServer = new IPEndPoint(ipAddress, port);
m_client = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
m_client.BeginConnect(m_epServer,
new AsyncCallback(ConnectCallback), m_client);
}
catch (Exception ex)
{ }
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
// Complete the connection.
m_client.EndConnect(ar); lstContent.Items.Add("Socket connected to "+
m_client.RemoteEndPoint.ToString());
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
} private void Receive()
{
try
{
// Begin receiving the data from the remote device.
m_client.BeginReceive(m_buffer, 0, m_buffer.Length, 0,
new AsyncCallback(ReceiveCallback), m_client);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
} private void ReceiveCallback(IAsyncResult ar)
{
try
{
// Read data from the remote device.
int bytesRead = m_client.EndReceive(ar); if (bytesRead > 0)
{
lstContent.Items.Add(Encoding.ASCII.GetString(m_buffer, 0, bytesRead));
}
m_client.BeginReceive(m_buffer, 0, m_buffer.Length, 0,
new AsyncCallback(ReceiveCallback), m_client);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
} private void Send(String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device.
m_client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), m_client);
} private void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState; // Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
lstContent.Items.Add(String.Format("Sent {0} bytes to server.", bytesSent));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
} private void btnSend_Click(object sender, EventArgs e)
{
if (txtMessage.Text != string.Empty)
{
Send(txtMessage.Text);
}
} private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Send("closeClient");//发送关闭客户端指令
}
}
}
C# Tcp 异步 Socket 断开
解决方案 »
- 工具箱加入com元件总是消失,是什么问题
- 救命!!
- 16进制转换10进制
- 急急急!!C#调用Dll文件,尝试读取写入受保护的内存。这通常指示其他内存已损坏
- 关于1.aspx.desiger.cs
- javascript怎么取得treeview的第一层节点?
- 请大家帮小弟解决一个问题
- 继承CollectionBase的类绑DataGrid,怎样实现增加删除?
- 不知道是应该学精windows 程序时, 还是学精web 程序好呢? 不知道怎样选择.个人的性格属于喜欢用脑型,不喜欢做重复工作那种人.
- 100分求sql数据库入门级源程序
- C#中多线程并发处理同一个静态类。请给下思维
- IIS 7.5 下 COMET的问题
//while (true)
//{
// allDone.Reset();
m_server.BeginAccept(
new AsyncCallback(AcceptCallback),
m_server);
// allDone.WaitOne();
//}
把这里面的注释去掉就可以连接多个客户端了,AcceptCallback方法里面的注释也要去掉,catch部分添加注释,出现异常输出即可,不要自动重新等待连接。
你用Ctrl+F5运行程序,出异常cmd窗口还在,异常会显示在上面。
谢谢您的回复,这里的注释是我自己加的,代码是我把MSDN里的console代码该成现在的Window代码了……如果把注释恢复的话,Server的主窗体将不会显示出来,我感觉是allDone把主线程阻塞了。我尝试了把上面的While放在了新的线程里,但那样还是不对。为什么啊?
正确的做法是在BeginAccept的回调函数AcceptCallback的最后再次执行BeginAccept,这样就可以做到处理完一个连接请求继续处理下一个。而且由于最初的BeginAccept不是循环内执行,只执行了一次就离开了,所以不会阻塞UI线程。
Socket handler = m_server.EndAccept(ar);
看下这两句,第一句被你屏蔽了,关键点也就是它,这两个Socket是不同的Socket,第一个listener通过ar获取的,那个才是你服务端用来监听的Socket,而第二个只是同客户端建立连接的Socket,不是监听用的Socket
//Socket listener = (Socket)ar.AsyncState;把这句恢复后还是和屏蔽时一样的错。
我在调用BeginAccept的时候是这样的
m_server.BeginAccept(new AsyncCallback(AcceptCallback),
m_server);
所以Socket listener = (Socket)ar.AsyncState;这句注释和不注释是一样的吧
我把AcceptCallBack改成了如下:public void AcceptCallback(IAsyncResult ar) {
try {
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar); handler.BeginReceive(m_buffer, 0, m_buffer.Length, 0,
new AsyncCallback(ReceiveCallback), handler); listener.BeginAccept(new AsyncCallback(AcceptCallback), handler);
} catch (Exception ex) {
MessageBox.Show(ex.ToString());
} }然后就晕了,listener和handler与m_server这三个Socket不一样吗?
在AcceptCallBack中调用BeginAccept的是m_server还是listener啊?
改成如上的代码后,没异常了,但是当客户端发送消息时,服务器就自动关闭了