读书人

套接字有关问题

发布时间: 2013-02-03 12:33:31 作者: rapoo

求助 套接字问题
我是学.net的新手,现在遇到了点问题 ,就是套接字的 多个客户端怎样给服务端发送信息 ,服务端是循环接收客户端的连接请求的,现在多个客户端连上后 只能一个客户端给服务端发送。高人请帮助 ,谢谢 .net
[解决办法]
服务器socket listen后,accept会生成1个新的连接,每次你都把这个连接给新的对象,就有多个连接,就可以同时接收多个客户端的发送了。
[解决办法]
服务器端的一个代码例子,包括接收客户端以及接收数据


/// <summary>
/// 收包处理委托
/// </summary>
/// <param name="buffer"></param>
/// <param name="socket"></param>
/// <returns></returns>
public delegate bool ReceivePacketHandle(byte[] buffer, Socket socket);

/// <summary>
/// 客户端接受委托
/// </summary>
public delegate void ClientChangedHandle(object state);

public abstract class PacketTransferBase
{
/// <summary>
/// Socket列表
/// </summary>
public SortedList<int, Socket> SocketClientList { get; private set; }

/// <summary>
/// 客户端接收事件
/// </summary>
public event ClientChangedHandle OnClientAccepted;

/// <summary>
/// 客户端关闭事件
/// </summary>
public event ClientChangedHandle OnClientClosed;

/// <summary>
/// 收包处理事件
/// </summary>
public event ReceivePacketHandle OnReceivePacket;

public PacketTransferBase()
{
SocketClientList = new SortedList<int, Socket>();
}

/// <summary>
/// 保存客户端,以待每次接收后进行判断等功能
/// </summary>
/// <param name="socketClient"></param>
protected void AddClient(Socket socketClient)
{
lock (SocketClientList)
{


HYTLogging.NCLogger.GetInstance().WriteInfoLog(string.Format("Add Socket:{0}.{1}", socketClient.Handle, socketClient.Connected));
SocketClientList.Add(socketClient.Handle.ToInt32(), socketClient);
}
//bufferList.Add(clientCount, new byte[1024]);
if (OnClientAccepted != null)
{
OnClientAccepted(socketClient.Handle.ToInt32());
}
}

/// <summary>
/// 接收信息
/// </summary>
/// <param name="ar"></param>
protected void ReceiveMessage(IAsyncResult ar)
{
try
{
StateObject so = (StateObject)ar.AsyncState;
Socket socket = so.workSocket;
//var socket = ar.AsyncState as Socket;

//方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.endreceive.aspx
var length = socket.EndReceive(ar);
byte[] actualData = new byte[length];
Array.Copy(so.buffer, 0, actualData, 0, length);
//fileManager.ReceivePacket(actualData);
HYTLogging.NCLogger.GetInstance().WriteInfoLog(string.Format("TCPServer.ReceiveMessage: buffer.{0} at Socket.{1} with buffer[23].{2},buffer[24].{3}", length, socket.Handle, so.buffer[23], so.buffer[24]));
//fileManager.ReceivePacket(actualData, socket);
//FileTransferManagerServer server = FileTransferManagerServer.GetInstance();
//server.ReceivePacket(actualData, socket);
bool continueReceive = false;


if (OnReceivePacket != null)
{
continueReceive = OnReceivePacket(actualData, socket);
}

//接收下一个消息(因为这是一个递归的调用,所以这样就可以一直接收消息了)
//socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);
if (continueReceive)
{
socket.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReceiveMessage), so);
}
else
{
Clean(socket);
//socket.Close();
}
}
catch (Exception ex)
{
HYTLogging.NCLogger.GetInstance().WriteInfoLog(ex.Message + ex.StackTrace);
}
}

/// <summary>
/// 从列表中移除Socket,并关闭Socket
/// </summary>
/// <param name="socket"></param>
protected void Clean(Socket socket)
{
HYTLogging.NCLogger.GetInstance().WriteInfoLog(string.Format("Clean Socket:{0}.{1}", socket.Handle, socket.Connected));
int socketHandle = socket.Handle.ToInt32();
lock (SocketClientList)
{
if (SocketClientList.ContainsKey(socketHandle))
{
SocketClientList.Remove(socketHandle);


}
}
socket.Close();
if (OnClientClosed != null)
{
OnClientClosed(socketHandle);
}
}
}

/// <summary>
/// TCP服务器端
/// </summary>
public class TCPServer : PacketTransferBase
{
public string ServerIP { get; set; }
public int ServerPort { get; set; }

//public Socket[] SocketClientList { get; private set; }

private static TCPServer tcpServer = new TCPServer();
Socket socketServer = null;
//FileManager fileManager = new FileManager(FileControl.FileReceive, TCPModel.TCPServer);
//FileManager fileManager = new FileManager(FileControl.FileSend, TransferModel.TCPServer);

private TCPServer()
{
//SocketClientList = new Socket[10];
//SocketClientList = new SortedList<int, Socket>();
}

public static PacketTransferBase GetInstance()
{
return tcpServer;
}

/// <summary>
/// 服务器端建立侦听
/// </summary>
public void CreatListener()
{
//创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)
socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

//将该socket绑定到主机上面的某个端口
//方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.bind.aspx
//socketServer.Bind(new IPEndPoint(IPAddress.Any, 4530));


socketServer.Bind(new IPEndPoint(IPAddress.Parse(ServerIP), ServerPort));

//启动监听,并且设置一个最大的队列长度
//方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.listen(v=VS.100).aspx
socketServer.Listen(100);

//开始接受客户端连接请求
//方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginaccept.aspx
socketServer.BeginAccept(new AsyncCallback(ClientAccepted), socketServer);
}

/// <summary>
/// 接收客户端
/// </summary>
/// <param name="ar"></param>
public void ClientAccepted(IAsyncResult ar)
{
try
{
var socketServer = ar.AsyncState as Socket;

//这就是客户端的Socket实例,我们后续可以将其保存起来
var socketClient = socketServer.EndAccept(ar);
AddClient(socketClient);

//接收客户端的消息(这个和在客户端实现的方式是一样的)
StateObject so = new StateObject();
so.workSocket = socketClient;
socketClient.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReceiveMessage), so);

//准备接受下一个客户端请求
socketServer.BeginAccept(new AsyncCallback(ClientAccepted), socketServer);
}
catch (Exception ex)
{
HYTLogging.NCLogger.GetInstance().WriteInfoLog(ex.Message + ex.StackTrace);
}
}
}

public class StateObject


{
public Socket workSocket = null;
public EndPoint tempRemoteEP = null;
public const int BUFFER_SIZE = 1024;
public byte[] buffer = new byte[BUFFER_SIZE];
}


[解决办法]
当客户端连接上服务器以后 你发送的时候还要用连接的那个tcpclient去发送消息
而不是重新实例化一个新的tcpclient 你所说的嵌套报错应该是在没有断开的情况下又重新连接了
端口号还用的是同一个

读书人网 >C#

热点推荐