读书人

关于一个异步socket的有关问题

发布时间: 2012-06-22 16:16:32 作者: rapoo

关于一个异步socket的问题
想学学C#里面的同步socket和异步socket,于是下了个例子,虽然有bug不过改改勉强可以用了,可是发现客户端多于一个就会报错
ex.Message = "The IAsyncResult object was not returned from the corresponding asynchronous method on this class.\r\nParameter name: asyncResult"
服务端是异步的,代码如下

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.Sockets;
using System.Net;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private delegate void threaddelegate();
byte[] RecvData = new byte[65535];
Socket serverSocket;
List <Socket> clientsocketlist=new List<Socket>();
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
int connectcount = 100;
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Any,int.Parse(textBox1.Text));
serverSocket.Bind(iep);
this.RecieveMsg.AppendText("开始监听.........\n");
serverSocket.Listen(connectcount);
serverSocket.BeginAccept(new AsyncCallback(AcceptConn), serverSocket);
}

void AcceptConn(IAsyncResult iar)
{
try
{
Socket listener = (Socket)iar.AsyncState;
Socket client = listener.EndAccept(iar);
this.clientsocketlist.Add(client);
IPAddress ip = ((System.Net.IPEndPoint)client.RemoteEndPoint).Address;

threaddelegate settext = delegate()
{
lock (this.RecieveMsg)
{
this.RecieveMsg.AppendText("服务器已连接" + ip.ToString() + "当前连接数"+this.clientsocketlist.Count.ToString());
}
};
this.RecieveMsg.Invoke(settext);

//开始接受来自该客户端的数据
client.BeginReceive(RecvData, 0, RecvData.Length, SocketFlags.None, new AsyncCallback(ReceiveData), client);
//继续接受其他客户端的连接
listener.BeginAccept(new AsyncCallback(AcceptConn), client);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}

void ReceiveData(IAsyncResult iar)
{
string strRecv;
Socket client = (Socket)iar.AsyncState;
int recv = client.EndReceive(iar);
if (recv == 0)
{
this.clientsocketlist.Remove(client);
client.Close();
}
else
{
threaddelegate settext = delegate()
{
lock (this.RecieveMsg)
{
string msgs = Encoding.Unicode.GetString(RecvData, 0, recv);
this.RecieveMsg.AppendText(msgs);
}
};
this.RecieveMsg.Invoke(settext);


//将接收到的数据再发送给客户端
client.BeginSend(RecvData, 0, recv, SocketFlags.None, new AsyncCallback(SendData), client);
}
//继续接收来自来客户端的数据
client.BeginReceive(RecvData, 0, RecvData.Length, SocketFlags.None, new AsyncCallback(ReceiveData), client);
}

void SendData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;
int sent = client.EndSend(iar);
}

private void button3_Click(object sender, EventArgs e)
{
foreach (Socket clients in this.clientsocketlist)
{
byte[] sendmsg = Encoding.Unicode.GetBytes(this.textBox2.Text+"\n");
clients.BeginSend(sendmsg, 0, sendmsg.Length, SocketFlags.None, new AsyncCallback(SendData), clients);
}
}
}
}

有谁能帮忙看看哪里出的问题么?或者能给我一个较好的异步服务端代码么?

[解决办法]
没有异步委托出去
[解决办法]

探讨
错误~
ex.Message = "The IAsyncResult object was not returned from the corresponding asynchronous method on this class.\r\nParameter name: asyncResult"
位置在AcceptConn这个函数里面的
Socket client = listener.……

[解决办法]
问题肯定是出在你在一个Form实例的范围内实例化一个serverSocket。具体的代码可能还要自己测试。

说实在的,我从来没有想过在Form去启动过什么Socket服务。
[解决办法]
监听就没必要异步了,while都不加sleep的循环就可以了,建立连接就可有异步了..有的时候我还是习惯开线程去处理,因为我觉得思路清晰点,这个异步同步的,多了就乱了,尤其还是判断数据是否传完,是否异常等..
[解决办法]
探讨

错误~
ex.Message = "The IAsyncResult object was not returned from the corresponding asynchronous method on this class.\r\nParameter name: asyncResult"
位置在AcceptConn这个函数里面的
Socket client = liste……

[解决办法]
探讨

答11L 其实那段代码是网上下的,只是为了简单理解下C#里的异步socket,可惜就是bug太多了,而且对于大量的使用回调函数不是很习惯,以前感觉java和delphi中的socket阻塞模式思路很清晰,不过因为阻塞模式不是万能的,据说异步模式可以节省资源,所以想学习下

答12L,那个委托的代码确实是多余了,因为总是出问题,所以我临时加进去想判断下连接是否正确

[解决办法]
呵呵,上面我回复时其实只是看到了你的代码的Connect部分,根本没有耐心往下看。而且你的问题也是出在connect部分,所以也因此懒得往下看。

刚刚想起来,看看你的缓冲区怎么声明吧。可是一看吓了我一大跳,连这个RecvData 也是共享的啊?看来你真的被顺序处理的程序给害得不轻啊。这样共享一堆东西,你一旦并行处理就会出现各种诡异的bug了。
[解决办法]
推荐你看看C_网络编程.pdf,然后写socket程序,手到擒来

读书人网 >C#

热点推荐