Клиент-сервер: как сделать чтобы задачи отправки и принятия сообщений работали параллельно - C#
Формулировка задачи:
Привет, есть один код асинхронного сервера, взял отсюда http://msdn.microsoft.com/ru-ru/library/dd335942.aspx#Section6 вот его код
Объясните пожалуйста, как работает функция
и для чего в ней этот код
Это был вопрос по серверу, а вот по клиенту. Сервер то работает, но у меня же клиент не идиот который может делать только что-то одно!! Проблема в том, что для того, чтобы получить что-то от сервера, клиент обязательно должен че-то отправить. А как сделать чтобы задачи отправки и принятия сообщений работали параллельно и не зависели друг от друга. Я-то пробовал как-то модифицировать уже имеющейся у меня код клиента, идея была в том, чтобы запустить операцию принятия сообщений в отдельном потоке, но понятное дело - у меня ничего не вышло. Вот этот смехотворный код
комментарии не мои.
Помогите, пожалуйста, разобраться с этим всем, умоляю!!!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using System.Net;
using System.Threading;
using System.Net.Sockets;
namespace ConsoleApplication3
{
class Program
{
class ThreadedServer
{
private Socket _serverSocket;
private int _port;
public ThreadedServer(int port) { _port = port; }
public void Start()
{
SetupServerSocket();
for (int i = 0; i < 10; i++)
_serverSocket.BeginAccept(new
AsyncCallback(AcceptCallback), _serverSocket);
}
private class ConnectionInfo
{
public Socket Socket;
public byte[] Buffer;
}
private List<ConnectionInfo> _connections = new List<ConnectionInfo>();
private void SetupServerSocket()
{
// Получаем информацию о локальном компьютере
/* IPHostEntry localMachineInfo =
Dns.GetHostEntry(Dns.GetHostName());*/
IPEndPoint myEndpoint = new IPEndPoint(IPAddress.Any, _port);
// Создаем сокет, привязываем его к адресу
// и начинаем прослушивание
_serverSocket = new Socket(
myEndpoint.Address.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(myEndpoint);
_serverSocket.Listen((int)
SocketOptionName.MaxConnections);
}
private void AcceptCallback(IAsyncResult result)
{
ConnectionInfo connection = new ConnectionInfo();
try
{
// Завершение операции Accept
Socket s = (Socket)result.AsyncState;
connection.Socket = s.EndAccept(result);
connection.Buffer = new byte[255];
lock (_connections) _connections.Add(connection);
// Начало операции Receive и новой операции Accept
connection.Socket.BeginReceive(connection.Buffer,
0, connection.Buffer.Length, SocketFlags.None,
new AsyncCallback(ReceiveCallback),
connection);
_serverSocket.BeginAccept(new AsyncCallback(
AcceptCallback), result.AsyncState);
}
catch (SocketException exc)
{
CloseConnection(connection);
Console.WriteLine("Socket exception: " +
exc.SocketErrorCode);
}
catch (Exception exc)
{
CloseConnection(connection);
Console.WriteLine("Exception: " + exc);
}
}
private void ReceiveCallback(IAsyncResult result)
{
ConnectionInfo connection =
(ConnectionInfo)result.AsyncState;
try
{
int bytesRead =
connection.Socket.EndReceive(result);
if (0 != bytesRead)
{
lock (_connections)
{
Console.WriteLine("начало " + Encoding.UTF8.GetString(connection.Buffer, 0, bytesRead) + " конец");
foreach (ConnectionInfo conn in
_connections)
{
if (connection != conn)
{
conn.Socket.Send(connection.Buffer,
bytesRead, SocketFlags.None);
}
}
}
connection.Socket.BeginReceive(
connection.Buffer, 0,
connection.Buffer.Length, SocketFlags.None,
new AsyncCallback(ReceiveCallback),
connection);
}
else CloseConnection(connection);
}
catch (SocketException exc)
{
CloseConnection(connection);
Console.WriteLine("Socket exception: " +
exc.SocketErrorCode);
}
catch (Exception exc)
{
CloseConnection(connection);
Console.WriteLine("Exception: " + exc);
}
}
private void CloseConnection(ConnectionInfo ci)
{
ci.Socket.Close();
lock (_connections) _connections.Remove(ci);
}
}
static void Main(string[] args)
{
ThreadedServer ts = new ThreadedServer(9393);
ts.Start();
Console.ReadLine();
}
}
}private void AcceptCallback(IAsyncResult result)
connection.Socket.BeginReceive(connection.Buffer,
0, connection.Buffer.Length, SocketFlags.None,
new AsyncCallback(ReceiveCallback),
connection);
_serverSocket.BeginAccept(new AsyncCallback(
AcceptCallback), result.AsyncState);using System; ///////////////////////////////////////////////////
using System.Collections.Generic;/////// Консольный стандарт //////////
using System.Text; ///////////////////////////////////////////////////
using System.Net.Sockets; ///// Вот он, родимый коллекшн классов //////
using System.Threading;
namespace MyFirstClient
{
class Program
{
public static void Recieve(Object sock)
{
byte[] remdata = { };
Socket s = (Socket)sock;
while (true)
{
try
{
s.Receive(remdata);
Console.WriteLine(Encoding.UTF8.GetString(remdata));
}
catch
{
s.Close();
}
}
}
static void Main(string[] args)
{
string data; // Юзерская дата
byte[] remdata = { }; // Дата с сервака
TcpClient Client = new TcpClient(); // создаем экземпляр
Console.Write("IP to connect to: 127.0.0.1"); // всякая фигня типа UI
string ip = "127.0.0.1";
Console.WriteLine("Port: 777 ");
int port = 9393;
Console.WriteLine("Connecting to server...");
try
{
Client.Connect(ip, port); // попробуем подконнектиться.
} // если не получится - эксепшн
catch
{
Console.WriteLine("Cannot connect to remote host!");
return;
}
Console.Write("done\r\nTo end, type 'END'");
Socket Sock = Client.Client; // нах всякие NetStream'ы
Thread thread = new Thread(Recieve);
thread.Start(Sock);
while (true) // базарим с сервером… если достало – пишем END
{
Console.Write("\r\n>");
data = Console.ReadLine();
if (data == "END")
break;
Sock.Send(Encoding.UTF8.GetBytes(data)); // преобразование
Console.WriteLine("ты послал: " + data);
// типов
try
{
Sock.Receive(remdata);
}
catch
{
Console.WriteLine("error");
}
Console.WriteLine("<" + Encoding.UTF8.GetString(remdata));
}
Client.Close();
Console.ReadLine();
}
}
}Решение задачи: «Клиент-сервер: как сделать чтобы задачи отправки и принятия сообщений работали параллельно»
textual
Листинг программы
private static void AcceptCompleted()
{
byte[] data = new byte[1024];
int recv = socket.Receive(data, data.Length, SocketFlags.None); // вот тут исключение
if (recv != 0)
{
string message = Encoding.UTF8.GetString(data, 0, recv);
Console.WriteLine(message);
}
}