在我的客户端应用中,每个客户端产生两个Socket
,一个用于接收,另一个用于发送并以这种方式连接到服务器:
async void Connect2Server(object obj)
{
recvArgs = new SocketAsyncEventArgs();
sendArgs = new SocketAsyncEventArgs();
recvArgs.AcceptSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sendArgs.AcceptSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
await recvArgs.AcceptSocket.ConnectAsync(host, port);
await recvArgs.AcceptSocket.SendAsync(Info<SockInfo>.Pack(new SockInfo()
{
Name = ClientName,
RecvArg = true
}), SocketFlags.None);
await sendArgs.AcceptSocket.ConnectAsync(host, port);
await sendArgs.AcceptSocket.SendAsync(Info<SockInfo>.Pack(new SockInfo()
{
Name = ClientName,
RecvArg = false
}), SocketFlags.None);
SetBuffer(recvArgs, bufferSize);
recvArgs.Completed += Receive;
recvArgs.AcceptSocket.ReceiveAsync(recvArgs);
}
,并且在服务器的AcceptAsync
回调中,我正在这样做:
void Accepted(object sender, SocketAsyncEventArgs e)
{
e.Completed -= Accepted;
e.Completed += CheckInfo;
SetBuffer(e, infoBufferLength);
e.AcceptSocket.ReceiveAsync(e);
Accept();
}
服务器的CheckInfo
函数检查客户端发送的SockInfo
。如果RecvArg = true
服务器将SocketAsyncEventArgs
分配为其SendArgs
,否则RecvArgs
如下:
void CheckInfo(object sender, SocketAsyncEventArgs e)
{
lock (Clients)
{
e.Completed -= CheckInfo;
var info = Info<SockInfo>.Unpack(e.Buffer);
Client c = Clients.FirstOrDefault(x => x.Name == info.Name);
if (c == null)
{
c = new Client();
c.Name = info.Name;
Clients.Add(c);
}
if (info.RecvArg)
{
c.SendArgs = e;
c.SendArgs.SetBuffer(null);
c.SendArgs.Completed += Sent;
}
else
{
c.RecvArgs = e;
SetBuffer(c.RecvArgs, bufferLength);
c.RecvArgs.Completed += Received;
c.RecvArgs.AcceptSocket.ReceiveAsync(c.RecvArgs);
}
}
}
Clients
是ObservableCollection
中的Client
:
class Client
{
public string Name { get; set; }
public SocketAsyncEventArgs SendArgs { get; set; }
public SocketAsyncEventArgs RecvArgs { get; set; }
}
和SockInfo
是具有以下属性的结构:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SockInfo
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string Name;
public bool RecvArg;
}
如果我设置了三个断点:客户端应用程序Connect2Server
函数的第二个和第四个await
的第一个和第二个,服务器端CheckInfo
的第三个和第二个,并以调试模式{{1 }}被击中两次,并且CheckInfo
函数中的c.SendArgs
和c.RecvArgs
都得到了CheckInfo
。但是,如果我删除前两个断点,SocketAsyncEventArgs
几乎总是被击中一次,而CheckInfo
仍然是c.RecvArgs
!
为什么以及如何确保null
始终获得其c.RecvArgs
?
另一个问题是我必须在SocketAsyncEventArgs
的{{1}}上拥有lock
吗?
编辑
另外两个功能可能与此问题(1)Clients
有关,服务器开始监听并将控制权传递给(2)CheckInfo
,每个创建一个全新的StartServer
时间被称为。这是这两个:
Accept
答案 0 :(得分:0)
我不知道为什么我必须手动调用这些pdb
,但不确定是否可以解决。我要在df.map_partitions(GetID).compute(scheduler='single-threaded')
和%debug
函数中进行一些更改,以下是那些更改:
callbacks
到目前为止,它与那些Accept
和Accepted
都可以正常工作!