2017-02-04 22 views
0

我已经在Stackoverflow上看到有这个问题的所有文章,但没有解决我的问题。 我创建的认证类客户端 - 服务器应用程序,我的建筑,使用TCP套接字:发送或接收数据的请求被禁止,因为套接字没有连接,也没有提供地址

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); 
} 
} 

现在在WPF应用程序,我用这个类注册和它的工作就好了,但是当涉及到登录它打破时服务器试图发送“确定”,并给我错误,我把这篇文章的标题。 这是它是如何在客户端做了登记:

Authentication _auth = new Authentication(SocketType.Stream, AddressFamily.InterNetwork, ProtocolType.Tcp); 
_auth.Connect(_serverIPAdd, _port); 
KeyValuePair<byte[], long> info = _auth.RegisterClientSide(reg.Username.Text, reg.Password.Text); 

和登录:

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); 
从这个可以看出

所以我做了相同的程序连接客户端到服务器,但在这种情况下,这通过和其他(登录)它失败。 IP地址是我的本地IP和端口是30012. 欢迎任何帮助。

+0

为什么你不检查'Connect()'失败的结果?你应该检查它是否返回-1。事实上,你最好只处理这个异常,因为-1不会告诉你为什么连接失败。另外,当你已经在构造函数中设置'_addressFamily'时,为什么在'Connect()'中设置?你完全忽略了通过这样做传递给构造函数的参数。 – itsme86

+0

@ itsme86设置Connect()中的_addressFamily来自我忘记删除的代码的旧版本。无论如何,我正在使用InterNetwork。关于例外,我只是缩短了本文的代码。我抓住每一个可能的例外,现在它只给我提到一个例外。 –

+0

为什么这个问题用[tag:wpf]标记,当只有与套接字相关的代码时......? –

回答

0

我发现我的错误在哪里。在第一次发送“OK”的LoginServerSide函数中,我使用了监听套接字(_socket),而不是在accept上创建的工作套接字(套接字)。

相关问题