C# 不允许发送或接收数据的请求,因为套接字未连接且未提供地址
我已经阅读了Stackoverflow上所有关于这个问题的帖子,但没有一篇解决了我的问题。 我已为正在构建的使用TCP套接字的客户端服务器应用程序创建了身份验证类:C# 不允许发送或接收数据的请求,因为套接字未连接且未提供地址,c#,wpf,sockets,C#,Wpf,Sockets,我已经阅读了Stackoverflow上所有关于这个问题的帖子,但没有一篇解决了我的问题。 我已为正在构建的使用TCP套接字的客户端服务器应用程序创建了身份验证类: public class Authentication { private Socket _socket; private AddressFamily _addressFamily; private SocketType _socketType; private ProtocolType _protocolType; private
public class Authentication
{
private Socket _socket;
private AddressFamily _addressFamily;
private SocketType _socketType;
private ProtocolType _protocolType;
private IPAddress _ipAddress;
private IPEndPoint _ipEndPoint;
private bool _running = true;
public Authentication(SocketType socketType, AddressFamily family, ProtocolType protocolType)
{
_addressFamily = family;
_socketType = socketType;
_protocolType = protocolType;
}
public int Connect(string ipAdd, int port)
{
try
{
_addressFamily = AddressFamily.InterNetwork;
_ipAddress = IPAddress.Parse(ipAdd);
_ipEndPoint = new IPEndPoint(_ipAddress, port);
_socket = new Socket(_addressFamily, _socketType, _protocolType);
_socket.Connect(_ipEndPoint);
return 0;
}
catch (Exception e)
{
return -1;
}
}
public int Listen(string ipAdd, int port, ClientManager clientManager)
{
try
{
_ipAddress = IPAddress.Parse(ipAdd);
_ipEndPoint = new IPEndPoint(_ipAddress, port);
_socket = new Socket(_addressFamily, _socketType, _protocolType);
_socket.Bind(_ipEndPoint);
while (_running)
{
_socket.Listen(30000);
Socket socket = _socket.Accept();
Thread thread = new Thread(() =>
{
ConnectionAccepted(ref socket, clientManager);
});
thread.Start();
}
return 0;
}
catch (Exception e)
{
return -1;
}
}
private void ConnectionAccepted(ref Socket socket, ClientManager clientManager)
{
try
{
string command = "";
do
{
byte[] len = new byte[4];
socket.Receive(len); //receive length of command
byte[] buffer = new byte[BitConverter.ToInt32(len, 0)];
socket.Receive(buffer);
command = Encoding.Unicode.GetString(buffer);
if (command.Contains("LOGIN"))
LoginServerSide(ref socket, clientManager);
else if (command.Contains("REGISTER"))
RegisterServerSide(socket, clientManager);
} while (!command.Contains("TERMINATE"));
Close(socket);
}
catch (Exception ex)
{
}
}
public bool LoginClientSide(string username, string password)
{
if (_socket == null)
return false;
//send action
byte[] login = Encoding.Unicode.GetBytes("LOGIN");
_socket.Send(BitConverter.GetBytes(login.Length));
_socket.Send(login);
byte[] ok = new byte[4];
_socket.Receive(ok);
if (Encoding.Unicode.GetString(ok) == "OK")
{
//send username
byte[] usernameBytes = Encoding.Unicode.GetBytes(username);
_socket.Send(usernameBytes);
ok = new byte[40];
_socket.Receive(ok); //OK: salt_value
if (Encoding.Unicode.GetString(ok).Split(':').First() == "OK")
{
//get salt
byte[] saltBytes = Encoding.Unicode.GetBytes(Encoding.Unicode.GetString(ok).Split(':').Last());
//send hashed password
byte[] passwordBytes = Encoding.Unicode.GetBytes(password);
byte[] hashedPassword = CreateHashedPassword(passwordBytes, saltBytes);
_socket.Send(hashedPassword);
_socket.Receive(ok);
if (Encoding.Unicode.GetString(ok) == "OK")
return true;
}
}
return false;
}
private void LoginServerSide(ref Socket socket, ClientManager clientManager)
{
byte[] ok = Encoding.Unicode.GetBytes("OK");
byte[] err = Encoding.Unicode.GetBytes("ER");
//response to action
_socket.Send(ok);
//receive username
byte[] buffer = new byte[50];
socket.Receive(buffer);
string username = Encoding.Unicode.GetString(buffer);
//check for existing user
if (clientManager.CheckForUser(username))
{
//user exists send OK: salt_value
byte[] salt = clientManager.GetSalt(username);
socket.Send(Encoding.Unicode.GetBytes("OK: " + salt));
//receive hashed password
buffer = new byte[64];
socket.Receive(buffer);
byte[] hashedPassword = clientManager.GetHashedPassword(username);
if (buffer.SequenceEqual(hashedPassword))
{
//password is ok
socket.Send(ok);
}
socket.Send(err);
}
//user does not exist
socket.Send(err);
}
public KeyValuePair<byte[], long> RegisterClientSide(string username, string password)
{
if (_socket == null)
throw new Exception("Socket not initialized");
byte[] register = Encoding.Unicode.GetBytes("REGISTER");
_socket.Send(BitConverter.GetBytes(register.Length));
_socket.Send(register);
byte[] ok = new byte[4];
_socket.Receive(ok);
string tmp = Encoding.Unicode.GetString(ok);
if (tmp == "OK")
{
//send username
byte[] usernameBytes = Encoding.Unicode.GetBytes(username);
_socket.Send(usernameBytes);
ok = new byte[4];
_socket.Receive(ok);
if (Encoding.Unicode.GetString(ok) == "OK")
{
//generate and send salt
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] salt = new byte[16];
rng.GetNonZeroBytes(salt);
_socket.Send(salt);
_socket.Receive(ok);
if (Encoding.Unicode.GetString(ok) == "OK")
{
//send hashed password
byte[] passwordBytes = CreateHashedPassword(Encoding.Unicode.GetBytes(password), salt);
_socket.Send(passwordBytes);
_socket.Receive(ok);
if (Encoding.Unicode.GetString(ok).Split(':').First() == "OK")
{
byte[] idBytes = new byte[8];
_socket.Receive(idBytes);
long id = BitConverter.ToInt64(idBytes, 0);
//created new user
return new KeyValuePair<byte[], long>(salt, id);
}
//server error
}
//server error
}
//username exists
}
return new KeyValuePair<byte[], long>();
}
private void RegisterServerSide(Socket socket, ClientManager clientManager)
{
byte[] ok = Encoding.Unicode.GetBytes("OK");
byte[] err = Encoding.Unicode.GetBytes("ER");
//response to action
socket.Send(ok);
//receive username
byte[] buffer = new byte[50];
socket.Receive(buffer);
string username = Encoding.Unicode.GetString(buffer).TrimEnd('\0');
//check for existing user
if (!clientManager.CheckForUser(username))
{
//user does not exist send ok
socket.Send(ok);
//receive salt
buffer = new byte[16];
socket.Receive(buffer);
//save salt
byte[] salt = new byte[16];
buffer.CopyTo(salt, 0);
//send ok
socket.Send(ok);
//receive hashed password
buffer = new byte[64];
socket.Receive(buffer);
//save hashed password
byte[] pass = new byte[64];
buffer.CopyTo(pass, 0);
//send ok: id
long id = clientManager.CreateNewUser(username, pass, salt);
socket.Send(Encoding.Unicode.GetBytes("OK"));
socket.Send(BitConverter.GetBytes(id));
}
else
socket.Send(err);
}
}
在服务器端:
Authentication _auth = new Authentication(SocketType.Stream, AddressFamily.InterNetwork, ProtocolType.Tcp);
_auth.Listen(_IPAddress, _port, this);
因此,从这里您可以看到,我对连接客户机到服务器执行了相同的过程,但在一种情况下,这个过程通过了,而在另一种情况下(登录)失败了。
IP地址是我的本地IP,端口是30012。
欢迎任何帮助。我已经找到了我的错误所在。在首次发送“OK”时的LoginServerSide函数中,我使用了侦听套接字(_socket)而不是在accept(socket)上创建的工作套接字。为什么不检查来自
Connect()
的失败结果?您应该检查它是否返回-1。事实上,您最好只处理异常,因为-1没有告诉您为什么它无法连接。另外,既然已经在构造函数中设置了\u addressFamily
,为什么还要在Connect()
中设置它?您这样做完全忽略了传递给构造函数的参数。@Connect()中的itsme86设置_addressFamily来自我忘记删除的旧版本代码。在任何情况下,我都在使用互联网。关于例外情况,我只是缩短了本文的代码。我捕捉到了每一个可能的异常,现在它只给出了我提到的一个。为什么这个问题被标记为,当只有套接字相关的代码时??
Authentication _auth = new Authentication(SocketType.Stream, AddressFamily.InterNetwork, ProtocolType.Tcp);
_auth.Connect(_serverIPAdd, _port);
bool login = _auth.LoginClientSide(login.textBox.Text, login.textBox1.Text)
Authentication _auth = new Authentication(SocketType.Stream, AddressFamily.InterNetwork, ProtocolType.Tcp);
_auth.Listen(_IPAddress, _port, this);