聊天服务申请

我正在为游戏做聊天服务,

我正在使用TCP侦听器客户端来获取帐户信息,某种登录服务。 我想知道我是否可以保持连接到服务器的客户端,以检查他是否还在线,并且如果他有新消息则继续向他发送消息。

我已经尝试为登录队列创建一个套接字列表,但是一旦我接受了一个新套接字,它就会将前一个套接字断开连接到服务器。

byte[] usernameByte = new byte[100]; int usernameRecieved = s.Receive(usernameByte); //guiController.setText(System.DateTime.Now + " Recieved Login..."); byte[] passByte = new byte[100]; int passRecieved = s.Receive(passByte); //guiController.setText(System.DateTime.Now + " Recieved Password..."); string username = ""; string password = ""; for (int i = 0; i < usernameRecieved; i++) username += (Convert.ToChar(usernameByte[i])); for (int i = 0; i < passRecieved; i++) password += (Convert.ToChar(passByte[i])); if (DomainController.getInstance().checkAccount(username, password)) { ASCIIEncoding asen = new ASCIIEncoding(); s.Send(asen.GetBytes("true")); s.Send(asen.GetBytes("U are succesfully logged in, press enter to continue")); guiController.setText(serverName,System.DateTime.Now+""); guiController.setText(serverName, "Sent Acknowledgement - Logged in"); } else { ASCIIEncoding asen = new ASCIIEncoding(); s.Send(asen.GetBytes("false")); s.Send(asen.GetBytes("U are NOT logged in, press enter to continue")); guiController.setText(serverName, System.DateTime.Now + ""); guiController.setText(serverName, "\nSent Acknowledgement - Not logged in"); } 

这是我目前用来检查用户发送给我的帐户信息的代码。 在我发送之后,用户放下了连接,然后继续下一个连接。

我已经尝试制作一个单独的套接字列表并逐个处理它们,但是由于前一个套接字的连接丢失,即使是两个尝试连接的不同机器也失败了。

有没有人有解决方案/保存套接字的方法,我可以使用它来使程序保持所有连接存活? 所以我可以从用户1发送消息给用户2,只需使用他们连接的sockets? 或者我是否需要在每次连接时添加ID?

编辑

客户端代码:(这只是一个测试客户端)

 while (true) { TcpClient tcpclnt = new TcpClient(); Console.WriteLine("Connecting....."); tcpclnt.Connect("xx.xxx.xxx.xx", 26862); // use the ipaddress as in the server program while(!(checkResponse(tcpclnt.GetStream()))) { Thread.Sleep(1000); } Console.WriteLine("Connected"); Console.Write("Enter the string to be transmitted : "); String str = Console.ReadLine(); if (str == "") { str = " "; } Stream stm = tcpclnt.GetStream(); ASCIIEncoding asen = new ASCIIEncoding(); byte[] ba = asen.GetBytes(str); Console.WriteLine("Transmitting....."); stm.Write(ba, 0, ba.Length); Console.Write("Enter the string to be transmitted : "); String str2 = Console.ReadLine(); if (str2 == "") { str2 = " "; } Stream stm2 = tcpclnt.GetStream(); ASCIIEncoding asen2 = new ASCIIEncoding(); byte[] ba2 = asen2.GetBytes(str2); Console.WriteLine("Transmitting....."); stm.Write(ba2, 0, ba2.Length); if (str == "false") { blijvenWerken = false; } byte[] bb = new byte[100]; int k = stm.Read(bb, 0, 100); for (int i = 0; i < k; i++) Console.Write(Convert.ToChar(bb[i])); byte[] bb2 = new byte[100]; int k2 = stm.Read(bb2, 0, 100); Console.Write("\n"); for (int i = 0; i < k2; i++) Console.Write(Convert.ToChar(bb2[i])); Console.WriteLine("\n"); tcpclnt.Close(); Thread.Sleep(1000); } 

服务器获取套接字:这一段代码在loginserver上,因为我每次只能接受1个套接字以保持连接活着,我将queueCount放在最大值为1.我希望能够列出一个我接受添加到用户帐户的套接字。

 while (loginServerOn) { if (queueCount < 1) { if (loginServer.getLoginListener().Pending()) { loginQueue.Add(loginServer.getSocket()); ASCIIEncoding asen = new ASCIIEncoding(); Socket s = loginQueue.First(); try { s.Send(asen.GetBytes("true")); queueCount++; } catch { loginQueue.Remove(s); } } } } 

返回已接受套接字的函数。

 public Socket getSocket() { return myList.AcceptSocket(); } 

编辑:问题的实质

我想将收到的socked或客户端添加到我的Account对象,因此每个连接都有一个链接到的帐户,当我想向某个帐户发送邮件时,它应该向绑定到该帐户的socked或客户端发送一条消息,你能帮我/告诉我如何实现这个目标吗?

这仍然是c#和套接字,但我的方法与你的不同。

我选择了“connectedCleint”的概念,其目的与您所谓的帐户类似。

我有一个名为ServerTerminal的类,它负责接受套接字连接和顶级管理。 在这我有:

  public Dictionary DictConnectedClients = new Dictionary(); 

所以这是我的sockethandle索引的连接客户端列表。

为了接受连接,我有一个例程:

 public void StartListen(int port) { socketClosed = false; IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, port); listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //bind to local IP Address... //if ip address is allready being used write to log try { listenSocket.Bind(ipLocal); } catch (Exception excpt) { // Deal with this.. write your own log code here ? socketClosed = true; return; } //start listening... listenSocket.Listen(100); // Max 100 connections for my app // create the call back for any client connections... listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null); } 

因此,当客户端连接它然后触发:

 private void OnClientConnection(IAsyncResult asyn) { if (socketClosed) { return; } try { Socket clientSocket = listenSocket.EndAccept(asyn); ConnectedClient connectedClient = new ConnectedClient(clientSocket, this, _ServerTerminalReceiveMode); //connectedClient.MessageReceived += OnMessageReceived; connectedClient.Disconnected += OnDisconnection; connectedClient.dbMessageReceived += OndbMessageReceived; connectedClient.ccSocketFaulted += ccSocketFaulted; connectedClient.StartListening(); long key = clientSocket.Handle.ToInt64(); if (DictConnectedClients.ContainsKey(connectedClient.SocketHandleInt64)) { // Already here - use your own error reporting.. } lock (DictConnectedClients) { DictConnectedClients[key] = connectedClient; } // create the call back for any client connections... listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null); } catch (ObjectDisposedException excpt) { // Your own code here.. } catch (Exception excpt) { // Your own code here... } } 

这对你来说至关重要的部分是:

  // create the call back for any client connections... listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null); 

这将设置serverterminal以接收新连接。

编辑:减少我的connectedclient版本:

 public class ConnectedClient { private Socket mySocket; private SocketIO mySocketIO; private long _mySocketHandleInt64 = 0; // These events are pass through; ConnectedClient offers them but really // they are from SocketIO public event TCPTerminal_ConnectDel Connected { add { mySocketIO.Connected += value; } remove { mySocketIO.Connected -= value; } } public event TCPTerminal_DisconnectDel Disconnected { add { mySocketIO.Disconnected += value; } remove { mySocketIO.Disconnected -= value; } } // Own Events public event TCPTerminal_TxMessagePublished TxMessageReceived; public delegate void SocketFaulted(ConnectedClient cc); public event SocketFaulted ccSocketFaulted; private void OnTxMessageReceived(Socket socket, TxMessage myTxMessage) { // process your message } private void OnMessageSent(int MessageNumber, int MessageType) { // successful send, do what you want.. } public ConnectedClient(Socket clientSocket, ServerTerminal ParentST) { Init(clientSocket, ParentST, ReceiveMode.Handler); } public ConnectedClient(Socket clientSocket, ServerTerminal ParentST, ReceiveMode RecMode) { Init(clientSocket, ParentST, RecMode); } private void Init(Socket clientSocket, ServerTerminal ParentST, ReceiveMode RecMode) { ParentServerTerminal = ParentST; _myReceiveMode = RecMode; _FirstConnected = DateTime.Now; mySocket = clientSocket; _mySocketHandleInt64 = mySocket.Handle.ToInt64(); mySocketIO = new SocketIO(clientSocket, RecMode); // Register for events mySocketIO.TxMessageReceived += OnTxMessageReceived; mySocketIO.MessageSent += OnMessageSent; mySocketIO.dbMessageReceived += OndbMessageReceived; } public void StartListening() { mySocketIO.StartReceiving(); } public void Close() { if (mySocketIO != null) { mySocketIO.Close(); mySocketIO = null; } try { mySocket.Close(); } catch { // We're closing.. don't worry about it } } public void SendMessage(int MessageNumber, int MessageType, string Message) { if (mySocket != null && mySocketIO != null) { try { mySocketIO.SendMessage(MessageNumber, MessageType, Message); } catch { // mySocketIO disposed inbetween check and call } } else { // Raise socket faulted event if (ccSocketFaulted != null) ccSocketFaulted(this); } } } 

}

一些有用的链接:

这是我开始的地方: http : //vadmyst.blogspot.com.au/2008/01/how-to-transfer-fixed-sized-data-with.html

http://vadmyst.blogspot.com.au/2008/03/part-2-how-to-transfer-fixed-sized-data.html

和..

C#套接字和multithreading

导致连接的套接字在.BeginReceive之后立即接受新消息?

http://nitoprograms.blogspot.com.au/2009/04/tcpip-net-sockets-faq.html

http://www.codeproject.com/Articles/83102/C-SocketAsyncEventArgs-High-Performance-Socket-Cod

我现在不能发布我的整个解决方案; 我需要调试的服务器代码存在缺陷; 加上我的雇主可能不希望发布的部分内容。 但我的代码基于Vadym对可变长度消息的作用。

当服务器准备好接受TCP连接时,它会创建一个新的TCP套接字,将它绑定到端口并使用Listen()方法。 当连接请求进入时,Listen()方法返回服务器和客户端用于通信的新套接字。 此时,服务器和客户端可以使用Send()和Receive()来回传递数据。 如果客户端断开连接,则服务器的Receive()以0字节的数据终止。

如果您想在接受第一个连接后等待另一个连接请求(即,当您与第一个客户端进行交互时),则可以执行此操作。 此时,您需要使用线程或异步方法之类的东西,这样您就可以处理多个连接。 基本上,您可以从侦听套接字接受Accept()连接请求。

麦克风