using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace ChatServer
{
public partial class Form1 : Form
{
private delegate void UpdateStatusCallback(string strMessage);
public Form1()
{
InitializeComponent();
}
private void btnListen_Click(object sender, EventArgs e)
{
// Parse the server's IP address out of the TextBox
IPAddress ipAddr = IPAddress.Parse(txtIp.Text);
// Create a new instance of the ChatServer object
ChatServer mainServer = new ChatServer(ipAddr);
// Hook the StatusChanged event handler to mainServer_StatusChanged
ChatServer.StatusChanged += new StatusChangedEventHandler(mainServer_StatusChanged);
// Start listening for connections
mainServer.StartListening();
// Show that we started to listen for connections
txtLog.AppendText("Monitoring for connections...\r\n");
}
public void mainServer_StatusChanged(object sender, StatusChangedEventArgs e)
{
// Call the method that updates the form
this.Invoke(new UpdateStatusCallback(this.UpdateStatus), new object[] { e.EventMessage });
}
private void UpdateStatus(string strMessage)
{
// Updates the log with the message
txtLog.AppendText(strMessage + "\r\n");
}
}
}
перевод в хроме
Код:
Код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
// Will hold the user name
private string UserName = "Unknown";
private string Date = DateTime.Now.ToString();
private StreamWriter swSender;
private StreamReader srReceiver;
private TcpClient tcpServer;
// Needed to update the form with messages from another thread
private delegate void UpdateLogCallback(string strMessage);
// Needed to set the form to a "disconnected" state from another thread
private delegate void CloseConnectionCallback(string strReason);
private Thread thrMessaging;
private IPAddress ipAddr;
private bool Connected;
private Thread t;
public Form1()
{
InitializeComponent();
}
// The event handler for application exit
public void OnApplicationExit(object sender, EventArgs e)
{
if (Connected == true)
{
// Closes the connections, streams, etc.
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
}
private void InitializeConnection()
{
// Parse the IP address from the TextBox into an IPAddress object
ipAddr = IPAddress.Parse("127.0.0.1");
// Start a new TCP connections to the chat server
tcpServer = new TcpClient();
while (Connected != true)
{
try
{
tcpServer.Connect(ipAddr, 1986);
// Helps us track whether we're connected or not
Connected = true;
}
catch
{
Thread.Sleep(4000);
}
}
// Prepare the form
UserName = "123";
// Send the desired username to the server
swSender = new StreamWriter(tcpServer.GetStream());
swSender.WriteLine(textBox2.Text);
swSender.Flush();
// Start the thread for receiving messages and further communication
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
private void ReceiveMessages()
{
// Receive the response from the server
srReceiver = new StreamReader(tcpServer.GetStream());
// If the first character of the response is 1, connection was successful
string ConResponse = srReceiver.ReadLine();
// If the first character is a 1, connection was successful
if (ConResponse[0] == '1')
{
// Update the form to tell it we are now connected
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { "Connected Successfully!" });
}
else // If the first character is not a 1 (probably a 0), the connection was unsuccessful
{
string Reason = "Not Connected: ";
// Extract the reason out of the response message. The reason starts at the 3rd character
Reason += ConResponse.Substring(2, ConResponse.Length - 2);
// Update the form with the reason why we couldn't connect
this.Invoke(new CloseConnectionCallback(this.CloseConnection), new object[] { Reason });
// Exit the method
return;
}
// While we are successfully connected, read incoming lines from the server
while (Connected)
{
// Show the messages in the log TextBox
try
{
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
catch
{
if (Connected = false)
{
try
{
tcpServer.Connect(ipAddr, 1986);
// Helps us track whether we're connected or not
Connected = true;
}
catch
{
Thread.Sleep(4000);
}
}
}
}
}
// This method is called from a different thread in order to update the log TextBox
private void UpdateLog(string strMessage)
{
// Append text also scrolls the TextBox to the bottom each time
textBox1.AppendText(strMessage + "\r\n");
}
// Closes a current connection
private void CloseConnection(string Reason)
{
// Show the reason why the connection is ending
textBox1.AppendText(Reason + "\r\n");
// Close the objects
t.Abort();
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
// Sends the message typed in to the server
private void SendMessage()
{
try
{
Date = DateTime.Now.ToString();
if (Date.Length >= 1)
{
swSender.WriteLine(Date);
swSender.Flush();
}
Thread.Sleep(1344);
}
catch
{
}
}
private void button1_Click(object sender, EventArgs e)
{
t = new Thread(WriteY);
t.Start();
}
private void WriteY()
{
while (true)
{
SendMessage();
}
}
private void button2_Click(object sender, EventArgs e)
{
// If we are not currently connected but awaiting to connect
if (Connected == false)
{
// Initialize the connection
InitializeConnection();
}
else // We are connected, thus disconnect
{
CloseConnection("Disconnected at user's request.");
}
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
// Will hold the user name
private string UserName = "Unknown";
private string Date = DateTime.Now.ToString();
private StreamWriter swSender;
private StreamReader srReceiver;
private TcpClient tcpServer;
// Needed to update the form with messages from another thread
private delegate void UpdateLogCallback(string strMessage);
// Needed to set the form to a "disconnected" state from another thread
private delegate void CloseConnectionCallback(string strReason);
private Thread thrMessaging;
private IPAddress ipAddr;
private bool Connected;
private Thread t;
public Form1()
{
InitializeComponent();
}
// The event handler for application exit
public void OnApplicationExit(object sender, EventArgs e)
{
if (Connected == true)
{
// Closes the connections, streams, etc.
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
}
private void InitializeConnection()
{
// Parse the IP address from the TextBox into an IPAddress object
ipAddr = IPAddress.Parse("127.0.0.1");
// Start a new TCP connections to the chat server
tcpServer = new TcpClient();
while (Connected != true)
{
try
{
tcpServer.Connect(ipAddr, 1986);
// Helps us track whether we're connected or not
Connected = true;
}
catch
{
Thread.Sleep(4000);
}
}
// Prepare the form
UserName = "123";
// Send the desired username to the server
swSender = new StreamWriter(tcpServer.GetStream());
swSender.WriteLine(textBox2.Text);
swSender.Flush();
// Start the thread for receiving messages and further communication
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
private void ReceiveMessages()
{
// Receive the response from the server
srReceiver = new StreamReader(tcpServer.GetStream());
// If the first character of the response is 1, connection was successful
string ConResponse = srReceiver.ReadLine();
// If the first character is a 1, connection was successful
if (ConResponse[0] == '1')
{
// Update the form to tell it we are now connected
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { "Connected Successfully!" });
}
else // If the first character is not a 1 (probably a 0), the connection was unsuccessful
{
string Reason = "Not Connected: ";
// Extract the reason out of the response message. The reason starts at the 3rd character
Reason += ConResponse.Substring(2, ConResponse.Length - 2);
// Update the form with the reason why we couldn't connect
this.Invoke(new CloseConnectionCallback(this.CloseConnection), new object[] { Reason });
// Exit the method
return;
}
// While we are successfully connected, read incoming lines from the server
while (Connected)
{
// Show the messages in the log TextBox
try
{
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
catch
{
if (Connected = false)
{
try
{
tcpServer.Connect(ipAddr, 1986);
// Helps us track whether we're connected or not
Connected = true;
}
catch
{
Thread.Sleep(4000);
}
}
}
}
}
// This method is called from a different thread in order to update the log TextBox
private void UpdateLog(string strMessage)
{
// Append text also scrolls the TextBox to the bottom each time
textBox1.AppendText(strMessage + "\r\n");
}
// Closes a current connection
private void CloseConnection(string Reason)
{
// Show the reason why the connection is ending
textBox1.AppendText(Reason + "\r\n");
// Close the objects
t.Abort();
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
// Sends the message typed in to the server
private void SendMessage()
{
try
{
Date = DateTime.Now.ToString();
if (Date.Length >= 1)
{
swSender.WriteLine(Date);
swSender.Flush();
}
Thread.Sleep(1344);
}
catch
{
}
}
private void button1_Click(object sender, EventArgs e)
{
t = new Thread(WriteY);
t.Start();
}
private void WriteY()
{
while (true)
{
SendMessage();
}
}
private void button2_Click(object sender, EventArgs e)
{
// If we are not currently connected but awaiting to connect
if (Connected == false)
{
// Initialize the connection
InitializeConnection();
}
else // We are connected, thus disconnect
{
CloseConnection("Disconnected at user's request.");
}
}
}
}
Молодец, код оформлять умеешь.
Код:
namespace ChatServer
{
// Holds the arguments for the StatusChanged event
public class StatusChangedEventArgs : EventArgs
{
// The argument we're interested in is a message describing the event
private string EventMsg;
// Property for retrieving and setting the event message
public string EventMessage
{
get
{
return EventMsg;
}
set
{
EventMsg = value;
}
}
// Constructor for setting the event message
public StatusChangedEventArgs(string strEventMsg)
{
EventMsg = strEventMsg;
}
}
// This delegate is needed to specify the parameters we're passing with our event
public delegate void StatusChangedEventHandler(object sender, StatusChangedEventArgs e);
class ChatServer
{
// This hash table stores users and connections (browsable by user)
public static Hashtable htUsers = new Hashtable(30); // 30 users at one time limit
// This hash table stores connections and users (browsable by connection)
public static Hashtable htConnections = new Hashtable(30); // 30 users at one time limit
// Will store the IP address passed to it
private IPAddress ipAddress;
private TcpClient tcpClient;
// The event and its argument will notify the form when a user has connected, disconnected, send message, etc.
public static event StatusChangedEventHandler StatusChanged;
private static StatusChangedEventArgs e;
// The constructor sets the IP address to the one retrieved by the instantiating object
public ChatServer(IPAddress address)
{
ipAddress = address;
}
// The thread that will hold the connection listener
private Thread thrListener;
// The TCP object that listens for connections
private TcpListener tlsClient;
// Will tell the while loop to keep monitoring for connections
bool ServRunning = false;
// Add the user to the hash tables
public static void AddUser(TcpClient tcpUser, string strUsername)
{
// First add the username and associated connection to both hash tables
ChatServer.htUsers.Add(strUsername, tcpUser);
ChatServer.htConnections.Add(tcpUser, strUsername);
// Tell of the new connection to all other users and to the server form
SendAdminMessage(htConnections[tcpUser] + " has joined us");
}
// Remove the user from the hash tables
public static void RemoveUser(TcpClient tcpUser)
{
// If the user is there
if (htConnections[tcpUser] != null)
{
// First show the information and tell the other users about the disconnection
SendAdminMessage(htConnections[tcpUser] + " has left us");
// Remove the user from the hash table
ChatServer.htUsers.Remove(ChatServer.htConnections[tcpUser]);
ChatServer.htConnections.Remove(tcpUser);
}
}
{
// Holds the arguments for the StatusChanged event
public class StatusChangedEventArgs : EventArgs
{
// The argument we're interested in is a message describing the event
private string EventMsg;
// Property for retrieving and setting the event message
public string EventMessage
{
get
{
return EventMsg;
}
set
{
EventMsg = value;
}
}
// Constructor for setting the event message
public StatusChangedEventArgs(string strEventMsg)
{
EventMsg = strEventMsg;
}
}
// This delegate is needed to specify the parameters we're passing with our event
public delegate void StatusChangedEventHandler(object sender, StatusChangedEventArgs e);
class ChatServer
{
// This hash table stores users and connections (browsable by user)
public static Hashtable htUsers = new Hashtable(30); // 30 users at one time limit
// This hash table stores connections and users (browsable by connection)
public static Hashtable htConnections = new Hashtable(30); // 30 users at one time limit
// Will store the IP address passed to it
private IPAddress ipAddress;
private TcpClient tcpClient;
// The event and its argument will notify the form when a user has connected, disconnected, send message, etc.
public static event StatusChangedEventHandler StatusChanged;
private static StatusChangedEventArgs e;
// The constructor sets the IP address to the one retrieved by the instantiating object
public ChatServer(IPAddress address)
{
ipAddress = address;
}
// The thread that will hold the connection listener
private Thread thrListener;
// The TCP object that listens for connections
private TcpListener tlsClient;
// Will tell the while loop to keep monitoring for connections
bool ServRunning = false;
// Add the user to the hash tables
public static void AddUser(TcpClient tcpUser, string strUsername)
{
// First add the username and associated connection to both hash tables
ChatServer.htUsers.Add(strUsername, tcpUser);
ChatServer.htConnections.Add(tcpUser, strUsername);
// Tell of the new connection to all other users and to the server form
SendAdminMessage(htConnections[tcpUser] + " has joined us");
}
// Remove the user from the hash tables
public static void RemoveUser(TcpClient tcpUser)
{
// If the user is there
if (htConnections[tcpUser] != null)
{
// First show the information and tell the other users about the disconnection
SendAdminMessage(htConnections[tcpUser] + " has left us");
// Remove the user from the hash table
ChatServer.htUsers.Remove(ChatServer.htConnections[tcpUser]);
ChatServer.htConnections.Remove(tcpUser);
}
}
Код:
// This is called when we want to raise the StatusChanged event
public static void OnStatusChanged(StatusChangedEventArgs e)
{
StatusChangedEventHandler statusHandler = StatusChanged;
if (statusHandler != null)
{
// Invoke the delegate
statusHandler(null, e);
}
}
// Send administrative messages
public static void SendAdminMessage(string Message)
{
StreamWriter swSenderSender;
// First of all, show in our application who says what
e = new StatusChangedEventArgs("Administrator: " + Message);
OnStatusChanged(e);
// Create an array of TCP clients, the size of the number of users we have
TcpClient[] tcpClients = new TcpClient[ChatServer.htUsers.Count];
// Copy the TcpClient objects into the array
ChatServer.htUsers.Values.CopyTo(tcpClients, 0);
// Loop through the list of TCP clients
for (int i = 0; i < tcpClients.Length; i++)
{
// Try sending a message to each
try
{
// If the message is blank or the connection is null, break out
if (Message.Trim() == "" || tcpClients == null)
{
continue;
}
// Send the message to the current user in the loop
swSenderSender = new StreamWriter(tcpClients.GetStream());
swSenderSender.WriteLine("Administrator: " + Message);
swSenderSender.Flush();
swSenderSender = null;
}
catch // If there was a problem, the user is not there anymore, remove him
{
RemoveUser(tcpClients);
}
}
}
// Send messages from one user to all the others
public static void SendMessage(string From, string Message)
{
StreamWriter swSenderSender;
// First of all, show in our application who says what
e = new StatusChangedEventArgs(From + " says: " + Message);
OnStatusChanged(e);
// Create an array of TCP clients, the size of the number of users we have
TcpClient[] tcpClients = new TcpClient[ChatServer.htUsers.Count];
// Copy the TcpClient objects into the array
ChatServer.htUsers.Values.CopyTo(tcpClients, 0);
// Loop through the list of TCP clients
for (int i = 0; i < tcpClients.Length; i++)
{
// Try sending a message to each
try
{
// If the message is blank or the connection is null, break out
if (Message.Trim() == "" || tcpClients == null)
{
continue;
}
// Send the message to the current user in the loop
swSenderSender = new StreamWriter(tcpClients.GetStream());
swSenderSender.WriteLine(From + " says: " + Message);
swSenderSender.Flush();
swSenderSender = null;
}
catch // If there was a problem, the user is not there anymore, remove him
{
RemoveUser(tcpClients);
}
}
}
public void StartListening()
{
// Get the IP of the first network device, however this can prove unreliable on certain configurations
IPAddress ipaLocal = ipAddress;
// Create the TCP listener object using the IP of the server and the specified port
tlsClient = new TcpListener(1986);
// Start the TCP listener and listen for connections
tlsClient.Start();
// The while loop will check for true in this before checking for connections
ServRunning = true;
// Start the new tread that hosts the listener
thrListener = new Thread(KeepListening);
thrListener.Start();
}
private void KeepListening()
{
// While the server is running
while (ServRunning == true)
{
// Accept a pending connection
tcpClient = tlsClient.AcceptTcpClient();
// Create a new instance of Connection
Connection newConnection = new Connection(tcpClient);
}
}
}
// This class handels connections; there will be as many instances of it as there will be connected users
class Connection
{
TcpClient tcpClient;
// The thread that will send information to the client
private Thread thrSender;
private StreamReader srReceiver;
private StreamWriter swSender;
private string currUser;
private string strResponse;
// The constructor of the class takes in a TCP connection
public Connection(TcpClient tcpCon)
{
tcpClient = tcpCon;
// The thread that accepts the client and awaits messages
thrSender = new Thread(AcceptClient);
// The thread calls the AcceptClient() method
thrSender.Start();
}
private void CloseConnection()
{
// Close the currently open objects
tcpClient.Close();
srReceiver.Close();
swSender.Close();
}
// Occures when a new client is accepted
private void AcceptClient()
{
srReceiver = new System.IO.StreamReader(tcpClient.GetStream());
swSender = new System.IO.StreamWriter(tcpClient.GetStream());
// Read the account information from the client
currUser = srReceiver.ReadLine();
// We got a response from the client
if (currUser != "")
{
// Store the user name in the hash table
if (ChatServer.htUsers.Contains(currUser) == true)
{
// 0 means not connected
swSender.WriteLine("0|This username already exists.");
swSender.Flush();
CloseConnection();
return;
}
else if (currUser == "Administrator")
{
// 0 means not connected
swSender.WriteLine("0|This username is reserved.");
swSender.Flush();
CloseConnection();
return;
}
else
{
// 1 means connected successfully
swSender.WriteLine("1");
swSender.Flush();
// Add the user to the hash tables and start listening for messages from him
ChatServer.AddUser(tcpClient, currUser);
}
}
else
{
CloseConnection();
return;
}
try
{
// Keep waiting for a message from the user
while ((strResponse = srReceiver.ReadLine()) != "")
{
// If it's invalid, remove the user
if (strResponse == null)
{
ChatServer.RemoveUser(tcpClient);
}
else
{
// Otherwise send the message to all the other users
ChatServer.SendMessage(currUser, strResponse);
}
}
}
catch
{
// If anything went wrong with this user, disconnect him
ChatServer.RemoveUser(tcpClient);
}
}
}
}
public static void OnStatusChanged(StatusChangedEventArgs e)
{
StatusChangedEventHandler statusHandler = StatusChanged;
if (statusHandler != null)
{
// Invoke the delegate
statusHandler(null, e);
}
}
// Send administrative messages
public static void SendAdminMessage(string Message)
{
StreamWriter swSenderSender;
// First of all, show in our application who says what
e = new StatusChangedEventArgs("Administrator: " + Message);
OnStatusChanged(e);
// Create an array of TCP clients, the size of the number of users we have
TcpClient[] tcpClients = new TcpClient[ChatServer.htUsers.Count];
// Copy the TcpClient objects into the array
ChatServer.htUsers.Values.CopyTo(tcpClients, 0);
// Loop through the list of TCP clients
for (int i = 0; i < tcpClients.Length; i++)
{
// Try sending a message to each
try
{
// If the message is blank or the connection is null, break out
if (Message.Trim() == "" || tcpClients == null)
{
continue;
}
// Send the message to the current user in the loop
swSenderSender = new StreamWriter(tcpClients.GetStream());
swSenderSender.WriteLine("Administrator: " + Message);
swSenderSender.Flush();
swSenderSender = null;
}
catch // If there was a problem, the user is not there anymore, remove him
{
RemoveUser(tcpClients);
}
}
}
// Send messages from one user to all the others
public static void SendMessage(string From, string Message)
{
StreamWriter swSenderSender;
// First of all, show in our application who says what
e = new StatusChangedEventArgs(From + " says: " + Message);
OnStatusChanged(e);
// Create an array of TCP clients, the size of the number of users we have
TcpClient[] tcpClients = new TcpClient[ChatServer.htUsers.Count];
// Copy the TcpClient objects into the array
ChatServer.htUsers.Values.CopyTo(tcpClients, 0);
// Loop through the list of TCP clients
for (int i = 0; i < tcpClients.Length; i++)
{
// Try sending a message to each
try
{
// If the message is blank or the connection is null, break out
if (Message.Trim() == "" || tcpClients == null)
{
continue;
}
// Send the message to the current user in the loop
swSenderSender = new StreamWriter(tcpClients.GetStream());
swSenderSender.WriteLine(From + " says: " + Message);
swSenderSender.Flush();
swSenderSender = null;
}
catch // If there was a problem, the user is not there anymore, remove him
{
RemoveUser(tcpClients);
}
}
}
public void StartListening()
{
// Get the IP of the first network device, however this can prove unreliable on certain configurations
IPAddress ipaLocal = ipAddress;
// Create the TCP listener object using the IP of the server and the specified port
tlsClient = new TcpListener(1986);
// Start the TCP listener and listen for connections
tlsClient.Start();
// The while loop will check for true in this before checking for connections
ServRunning = true;
// Start the new tread that hosts the listener
thrListener = new Thread(KeepListening);
thrListener.Start();
}
private void KeepListening()
{
// While the server is running
while (ServRunning == true)
{
// Accept a pending connection
tcpClient = tlsClient.AcceptTcpClient();
// Create a new instance of Connection
Connection newConnection = new Connection(tcpClient);
}
}
}
// This class handels connections; there will be as many instances of it as there will be connected users
class Connection
{
TcpClient tcpClient;
// The thread that will send information to the client
private Thread thrSender;
private StreamReader srReceiver;
private StreamWriter swSender;
private string currUser;
private string strResponse;
// The constructor of the class takes in a TCP connection
public Connection(TcpClient tcpCon)
{
tcpClient = tcpCon;
// The thread that accepts the client and awaits messages
thrSender = new Thread(AcceptClient);
// The thread calls the AcceptClient() method
thrSender.Start();
}
private void CloseConnection()
{
// Close the currently open objects
tcpClient.Close();
srReceiver.Close();
swSender.Close();
}
// Occures when a new client is accepted
private void AcceptClient()
{
srReceiver = new System.IO.StreamReader(tcpClient.GetStream());
swSender = new System.IO.StreamWriter(tcpClient.GetStream());
// Read the account information from the client
currUser = srReceiver.ReadLine();
// We got a response from the client
if (currUser != "")
{
// Store the user name in the hash table
if (ChatServer.htUsers.Contains(currUser) == true)
{
// 0 means not connected
swSender.WriteLine("0|This username already exists.");
swSender.Flush();
CloseConnection();
return;
}
else if (currUser == "Administrator")
{
// 0 means not connected
swSender.WriteLine("0|This username is reserved.");
swSender.Flush();
CloseConnection();
return;
}
else
{
// 1 means connected successfully
swSender.WriteLine("1");
swSender.Flush();
// Add the user to the hash tables and start listening for messages from him
ChatServer.AddUser(tcpClient, currUser);
}
}
else
{
CloseConnection();
return;
}
try
{
// Keep waiting for a message from the user
while ((strResponse = srReceiver.ReadLine()) != "")
{
// If it's invalid, remove the user
if (strResponse == null)
{
ChatServer.RemoveUser(tcpClient);
}
else
{
// Otherwise send the message to all the other users
ChatServer.SendMessage(currUser, strResponse);
}
}
}
catch
{
// If anything went wrong with this user, disconnect him
ChatServer.RemoveUser(tcpClient);
}
}
}
}
Да вопросов нету в Гугле хроме проще переводить коментарии
ХЗ у меня раньше был проэкт для америкосов писал и чтото лень под наших заказчиков переписывать коментарии... Все можно тему удалять я все переписал...