过去一天左右,我一直在努力学习插座。我认为建立一个基本的聊天客户端和服务器是一个好主意,我试图创建一个异步服务器,所以我不需要使用大量的线程等我已经遇到了问题我根本无法修复。当我启动我的服务器时,它会通过所有ok并等待它需要等待连接的点。然后我启动了我的临时客户'这只是简单地发送一个字符串,我的服务器崩溃了SocketException
消息
附加信息:由于套接字未连接而且(使用sendto调用在数据报套接字上发送时)未提供发送或接收数据的请求,因此未提供地址
当我的套接字必须首先接受连接时,我看不到它是如何连接的。我一直在使用本教程(https://msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx)作为指南,看了我的代码和教程,但仍然不了解我做错了什么,有人可以帮助我吗?
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Chat_Application
{
class Server
{
private Socket serverSocket = null;
private volatile ArrayList connections = null; // will hold all client sockets
private const int port = 1090;
private IPAddress ipAddress = null;
private IPEndPoint ipEndPoint = null;
private Thread listenThread = null; // seperate thread to run the server
private ManualResetEvent allDone = null;
public Server()
{
this.serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.connections = new ArrayList();
ipAddress = IPAddress.Parse(GetLocalIPv4(NetworkInterfaceType.Ethernet));
ipEndPoint = new IPEndPoint(ipAddress, port);
listenThread = new Thread(StartListen);
allDone = new ManualResetEvent(false);
}
public void Start()
{
listenThread.Start();
}
public void StartListen()
{
this.serverSocket.Bind(ipEndPoint);
this.serverSocket.Listen(20);
Program.mainWin.console.Text += "\n<INFO> Socket bound, listening for connections...";
while (true)
{
allDone.Reset();
serverSocket.BeginAccept(new AsyncCallback(AcceptConnectionAsync), serverSocket);
Program.mainWin.console.Text += "\n<INFO> Conncetion accepted...";
allDone.WaitOne();
}
}
public void AcceptConnectionAsync(IAsyncResult AR)
{
Byte[] bufferBytes = new byte[1024];
allDone.Set();
Socket client = (Socket) AR.AsyncState;
int x = client.Receive(bufferBytes);
Program.mainWin.console.Text += System.Text.Encoding.Default.GetString(bufferBytes);
}
public string GetLocalIPv4(NetworkInterfaceType _type)
{
string output = "";
foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
{
if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)
{
foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
{
output = ip.Address.ToString();
}
}
}
}
return output;
}
}
}
答案 0 :(得分:1)
您永远不会调用EndAccept
(来自您关联的示例):
// Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar); // This right here
ar.AsyncState
中的套接字是监听套接字,而不是连接的客户端。 AsyncState是一个任意对象,可用于将信息传递给回调方法(AcceptConnectionAsync
)。在这种情况下,您传递的是serverSocket(下面的第二个参数):
serverSocket.BeginAccept(new AsyncCallback(AcceptConnectionAsync), serverSocket);
当您在侦听套接字上调用EndAccept
时,您将获得一个 new Socket
实例,该实例是与客户端的特定连接 - 您的侦听器套接字将启动异步请求接受while
中StartListen
循环中的其他连接。 EndAccept
返回的套接字处于连接状态,并准备根据此特定回调调用与另一个端点进行通信(因此,需要提供IAsyncResult
作为参数)。
这被称为异步编程模型。 MSDN has some great information就此而言(像往常一样)。