c# 异步socket关闭问题,在线等,分还可以在加......................................................

b403945133 2015-05-19 09:53:15

public bool btnstatu = true; //开始停止服务按钮状态
public Thread myThread; //声明一个线程实例

//开始停止服务按钮
private void startService_Click(object sender, EventArgs e)
{
if (btnstatu)
{
// 实例化新线程
myThread = new Thread(new ThreadStart(Listen));
btnstatu = false;
}
else
{
try
{
newsock.Shutdown(SocketShutdown.Both);
}
catch { }
newsock.Close();
myThread.Abort();
btnstatu = true;

}

GC.Collect();//即使垃圾回收
GC.WaitForPendingFinalizers();

}

//监听函数
public void Listen()
{
//后台线程
Thread.CurrentThread.IsBackground = true;
//初始化SOCKET实例
newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//初始化终结点实例
ipa = IPAddress.Any; //IPAddress.Parse(textBox1.Text.Trim());

setPort = int.Parse(serverport.Text.Trim());
localEP=new IPEndPoint(ipa,setPort);
try
{
newsock.IOControl(IOControlCode.KeepAliveValues, GetKeepAliveSetting(1,1000,1000), null);
//绑定
newsock.Bind(localEP);
//监听
newsock.Listen(500);
//开始接受连接,异步。

while (true)
{
AcceptDone.Reset();
try
{
newsock.BeginAccept(new AsyncCallback(AcceptCallback), newsock);
}
catch
{
Thread.Sleep(1000);
newsock.BeginAccept(new AsyncCallback(AcceptCallback), newsock);
}
AcceptDone.WaitOne();
}
}
catch (Exception ex)
{
showClientMsg(ex.Message);
}

}

public void AcceptCallback(IAsyncResult ar) //accpet的回调处理函数
{

AcceptDone.Set();
server1 = (Socket)ar.AsyncState;
//将接收到的Socket传给Client,然后继续监听
Client = server1.EndAccept(ar);

Control.CheckForIllegalCrossThreadCalls = false;
DateTimeOffset now = DateTimeOffset.Now;
//将提示信息发送给客户端,并在服务端显示连接信息。
ClientIP = (Client.RemoteEndPoint as IPEndPoint).Address;//获取远程端口的ip地址
ClientPORT = (Client.RemoteEndPoint as IPEndPoint).Port;//获取远程的端口
ClientName = "IP:" + ClientIP + "Port:" + ClientPORT;

StateObject state = new StateObject();
state.workSocket = Client;
state.socketid = ClientName;

try
{
Client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
catch (SocketException)
{
Client.Shutdown(SocketShutdown.Both);
Client.Close();
}

}
public void ReadCallback(IAsyncResult ar)
{
try
{
String content = String.Empty;
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int bytesRead = handler.EndReceive(ar);
;
if (bytesRead == 0)
{
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}

if (bytesRead > 0)
{
string stringdata = ""; //接收到的数据
stringdata += Encoding.GetEncoding("utf-8").GetString(state.buffer, 0, bytesRead);
//显示客户端发送过来的信息
showClientMsg("【" + state.socketid + "】发送消息" + stringdata + "时间:" + DateTime.Now.ToString() + "\r\n");

}

handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch
{
}
}



问题是点击关闭服务按钮,即btnstatu = false时,就提示

该如何关闭异步产生的socket

...全文
902 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
pizhu3053 2017-10-13
  • 打赏
  • 举报
回复
你好,我想问一下,现在解决了吗?我也是断开不会写,写出来报错。哎
b403945133 2015-05-25
  • 打赏
  • 举报
回复
b403945133 2015-05-22
  • 打赏
  • 举报
回复
我的问题就是,两个按钮,一个开启,一个关闭,现在关闭不会写....
b403945133 2015-05-22
  • 打赏
  • 举报
回复
引用 26 楼 nacheng 的回复:
关闭的时候同时关闭 private void ClearClient() { if (AcceptSockAsyn != null) { AcceptSockAsyn.Dispose(); AcceptSockAsyn = null; } EndPoint[] ep = new EndPoint[connectClient.Keys.Count]; connectClient.Keys.CopyTo(ep, 0); Token token; SocketAsyncEventArgs args; for (int i = 0; i < ep.Length; ++i) { args = connectClient[ep[i]]; token = args.UserToken as Token; CloseClientSocket(token); } connectClient.Clear(); ep = null; }
同时关闭时指的关闭所有socket吗,看不太懂啊
那城 2015-05-21
  • 打赏
  • 举报
回复
加上这个方法
那城 2015-05-21
  • 打赏
  • 举报
回复
关闭的时候同时关闭
private void ClearClient()
{
if (AcceptSockAsyn != null)
{
AcceptSockAsyn.Dispose();
AcceptSockAsyn = null;
}

EndPoint[] ep = new EndPoint[connectClient.Keys.Count];
connectClient.Keys.CopyTo(ep, 0);

Token token;
SocketAsyncEventArgs args;
for (int i = 0; i < ep.Length; ++i)
{
args = connectClient[ep[i]];
token = args.UserToken as Token;
CloseClientSocket(token);
}

connectClient.Clear();
ep = null;
}
b403945133 2015-05-21
  • 打赏
  • 举报
回复
顶................
b403945133 2015-05-20
  • 打赏
  • 举报
回复
引用 17 楼 Z65443344 的回复:
listenerThread.Join() 表示阻塞当前线程,等待listenerThread退出
阻塞界面主线程,直到监听线程完成,是这样吗, 如果是的话,这样能停止当前的监听服务吗
於黾 2015-05-20
  • 打赏
  • 举报
回复
listenerThread.Join() 表示阻塞当前线程,等待listenerThread退出
b403945133 2015-05-20
  • 打赏
  • 举报
回复
引用 13 楼 Forty2 的回复:
[quote=引用 11 楼 tcmakebest 的回复:] 关闭连接必然会报错的,这就是正常流程,关闭的时候只要 Shutdown 就行, 捕获错误后再 Close 另外楼主的监听部分, 使用了异步 BeginAccept, 却又用了AcceptDone来同步, 不是多此一举吗. 接收数据的部分收过一次就关闭连接了, 有可能数据没有一次性全部传过来, 需要考虑多次接收, 楼主的代码是有隐患的.
关闭连接倒是不一定报错。 监听部分的确是‘多此一举’。 以下是一个如何‘开始/停止’监听的示例,示例用了TcpListener,自己换成Socket也可以,原理是相同的。 建议新建一个WinForm项目,然后拷贝以下代码,并编译运行,按'Start'按钮开始侦听。 测试客户可以用浏览器,在地址栏输入http://localhost:5678即可。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        FlowLayoutPanel layoutPanel = new FlowLayoutPanel() { Dock = DockStyle.Fill };
        layoutPanel.Controls.AddRange(new Control[] { textBoxPort, buttonStartStop, listBoxLog});
        buttonStartStop.Click += button1_Click;
        this.Controls.Add(layoutPanel);
    }

    void button1_Click(object sender, EventArgs e)
    {
        listening = !listening;
        if (listening)
        {
            int port = int.Parse(textBoxPort.Text);
            listenerThread = new Thread(ListenerThread) { IsBackground = true };
            listenerThread.Start(port);
        }
        else
        {
            listenerThread.Join();
        }
        buttonStartStop.Text = listening ? "Stop" : "Start";
    }

    void ListenerThread(object state)
    {
        try
        {
            TcpListener listener = new TcpListener(IPAddress.Any, (int)state);
            listener.Start();
            Log("Listener started on " + state);
            while (listening)
            {
                if (listener.Server.Poll(100, SelectMode.SelectRead)) // 一次最多阻塞100毫秒,以便检查listening标志。
                {
                    Socket socket = listener.AcceptSocket();
                    Log("Client connected - " + socket.RemoteEndPoint);
                    StateObject so = new StateObject() {socket = socket };
                    socket.BeginReceive(so.buffer, 0, so.buffer.Length, SocketFlags.None, OnReceived, so);
                }
            }
            listener.Stop();
            Log("Listener stopped");
        }
        catch (Exception ex)
        {
            Log("Exception in ListenerThread: " + ex.Message);
        }
    }

    void OnReceived(IAsyncResult iar)
    {
        try
        {
            StateObject so = (StateObject)iar.AsyncState;
            int received = so.socket.EndReceive(iar);
            if (received > 0)
            {
                string msg = Encoding.UTF8.GetString(so.buffer, 0, received);
                so.socket.Send(Encoding.UTF8.GetBytes(DateTime.Now.ToString("s")));
                Log(so.socket.RemoteEndPoint + " -> " + msg);
            }
            Log("Closing connection with " + so.socket.RemoteEndPoint);
            so.socket.Shutdown(SocketShutdown.Both);
            so.socket.Close();
        }
        catch (Exception ex)
        {
            Log("Exception in OnReceived: " + ex.Message);
        }
    }

    void Log(string line)
    {
        if (this.InvokeRequired)
        {
            this.BeginInvoke((Action)delegate { Log(line); });
            return;
        }
        listBoxLog.Items.Add(string.Format("[{0:s}] {1}", DateTime.Now, line));
    }

    TextBox textBoxPort = new TextBox() { Text = "5678" };
    Button buttonStartStop = new Button() { Text = "Start" };
    ListBox listBoxLog = new ListBox() { Size = new Size(400, 300) };
    Thread listenerThread;
    bool listening = false;

    private class StateObject
    {
        public Socket socket;
        public byte[] buffer = new byte[4 * 1024];
    }
}
[/quote] listenerThread.Join()这一句代码是什么意思啊,是关掉所有后台线程,还是只是关掉监听线程,刚接触socket,还请大神多多指教
编程有钱人了 2015-05-20
  • 打赏
  • 举报
回复
客户端意外退出,用try处理
b403945133 2015-05-20
  • 打赏
  • 举报
回复
引用 23 楼 nacheng 的回复:
try { sSocket.Shutdown(SocketShutdown.Both); } catch (System.Exception ex) { } sSocket.Close();
这样监听线程是否也关掉了呢?,这个时候如果我在点击开启服务,会怎么样呢,是重新开个线程吗
那城 2015-05-20
  • 打赏
  • 举报
回复
try { sSocket.Shutdown(SocketShutdown.Both); } catch (System.Exception ex) { } sSocket.Close();
b403945133 2015-05-20
  • 打赏
  • 举报
回复
引用 21 楼 Z65443344 的回复:
你可以把 listenerThread.Join() 理解为 while( listenerThread.IsAlive) { sleep(1); } 当然内部实现不会这么低级就是了,但是作用是一样的,当然用sleep来阻塞当前线程效率就低的多了
那该如何关闭socket服务器端啊?,大神帮帮忙吧
於黾 2015-05-20
  • 打赏
  • 举报
回复
你可以把 listenerThread.Join() 理解为 while( listenerThread.IsAlive) { sleep(1); } 当然内部实现不会这么低级就是了,但是作用是一样的,当然用sleep来阻塞当前线程效率就低的多了
於黾 2015-05-20
  • 打赏
  • 举报
回复
引用 18 楼 b403945133 的回复:
[quote=引用 17 楼 Z65443344 的回复:] listenerThread.Join() 表示阻塞当前线程,等待listenerThread退出
阻塞界面主线程,直到监听线程完成,是这样吗, 如果是的话,这样能停止当前的监听服务吗[/quote] 是当前线程 当然如果你把代码写在主线程里,阻塞的就是主线程 跟停止不停止没有任何关系,这是线程同步,一个线程等待另一个线程执行完毕之后再执行后续代码
Poopaye 2015-05-19
  • 打赏
  • 举报
回复
把socket关掉就行了
江南小鱼 2015-05-19
  • 打赏
  • 举报
回复
1、设置布尔变量(isListening),用来标识是否正在监听,只有isListening为tru时,在异步接收 2、窗体关闭前,释放监听(isListening置为false,socket对象进行close、赋null值)
b403945133 2015-05-19
  • 打赏
  • 举报
回复
自个顶顶顶............................................
yghuaa 2015-05-19
  • 打赏
  • 举报
回复
我来踩踩 没有分数来发提问了,我来踩踩 没有分数来发提问了,我来踩踩 没有分数来发提问了,
加载更多回复(10)

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧