Во-первых, я не знаю, является ли Stackoverflow лучшим сайтом для публикации такого рода сообщений, но я не знаю других подобных сайтов.
Чтобы правильно понять программирование tcp на C#, я решил сделать все возможные способы с нуля. Вот что я хочу знать (не в правильном порядке): - Простой сервер сокетов с одним потоком (эта статья) - Сервер сокетов с несколькими потоками (я не знаю, как это сделать, потому что потоки сложны) - Сервер сокетов с простым потоком (поместите управление клиентом в другом потоке) - Сервер сокетов с несколькими потоками - Использование tcpListener - Использование async / Await - Использование задач Конечная цель - узнать, как сделать лучший сервер tcp, не просто копируя/вставляя некоторые части прихода, но правильно понимая все.
Итак, это моя первая часть: однопоточный tcp-сервер.
Там есть мой код, но не думаю, что кто-то что-то подправит, потому что это вполне себе копия из MSDN: http://msdn.microsoft.com/en-us/library/6y0e13d3(v=vs.110).aspx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace SimpleOneThreadSocket
{
public class ServerSocket
{
private int _iPport = -1;
private static int BUFFER_SIZE = 1024;
private Socket _listener = null;
public ServerSocket(int iPort)
{
// Create a TCP/IP socket.
this._listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Save the port
this._iPport = iPort;
}
public void Start()
{
byte[] buffer = null;
String sDatasReceived = null;
// Bind the socket to loopback address
try
{
this._listener.Bind(new System.Net.IPEndPoint(System.Net.IPAddress.Loopback, _iPport));
this._listener.Listen(2);
}
catch (Exception e)
{
System.Console.WriteLine(e.ToString());
}
// Listening
try
{
Console.WriteLine("Server listening on 127.0.0.1:" + _iPport);
while (true)
{
Socket client = this._listener.Accept();
Console.WriteLine("Incoming connection from : " + IPAddress.Parse(((IPEndPoint)client.RemoteEndPoint).Address.ToString()) + ":" + ((IPEndPoint)client.RemoteEndPoint).Port.ToString());
// An incoming connection needs to be processed.
while (true)
{
buffer = new byte[BUFFER_SIZE];
int bytesRec = client.Receive(buffer);
sDatasReceived += Encoding.ASCII.GetString(buffer, 0, bytesRec);
if (sDatasReceived.IndexOf("<EOF>") > -1)
{
// Show the data on the console.
Console.WriteLine("Text received : {0}", sDatasReceived);
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(sDatasReceived);
client.Send(msg);
sDatasReceived = "";
buffer = null;
}
else if (sDatasReceived.IndexOf("exit") > -1)
{
client.Shutdown(SocketShutdown.Both);
client.Close();
sDatasReceived = "";
buffer = null;
break;
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
Но у меня есть несколько вопросов по этому поводу:
Метод прослушивания из сокета имеет параметр: отставание. Согласно MSDN, отставание — это количество доступных подключений. Я не знаю, почему, когда я ставлю 0, я могу подключиться к своему серверу с помощью нескольких сеансов Telnet. РЕДАКТИРОВАТЬ: 0 и 1 разрешают 2 соединения (1 текущее, 1 ожидающее), 2 разрешают 3 соединения (1 текущее, 2 ожидающих) и т. д. Так что я не очень хорошо понял значение MSDN.
Можете ли вы подтвердить, что метод Accept будет принимать каждое соединение одно за другим, поэтому я вижу текст из разных сеансов Telnet на моем сервере?
Можете ли вы подтвердить (мой сервер является библиотекой C #), я не могу убить свой сервер (с помощью такого кода), не убивая процесс? Это может быть возможно с потоками, но это придет позже.
Если что-то не так в моем коде, пожалуйста, помогите мне :)
Я скоро вернусь с простым сервером сокетов с несколькими потоками, но я не знаю, как это сделать (я думаю, что один шаг доступен перед использованием потоков или async/await).