首先,我不知道Stackoverflow是否是发布此类邮件的最佳网站,但我不知道其他网站是这样的。
为了更好地理解C#中的tcp编程,我决定从头开始做所有可能的方法。这是我想知道的(不是正确的顺序: - 简单的一个线程套接字服务器(本文) - 简单的多线程套接字服务器(我不知道如何,导致线程复杂) - 简单的线程套接字服务器(将客户端管理放在另一个线程中) - 多线程套接字服务器 - 使用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());
}
}
}
}
但我对此有一些疑问:
来自Socket的Listen方法有一个参数:backlog。根据MSDN,积压是可用连接的数量。我不知道为什么,当我把0,我可以通过多个Telnet会话连接到我的服务器。编辑:0&amp; 1都允许2个连接(1个电流,1个待处理),2个允许3个连接(1个电流,2个待处理等)......所以我不太了解MSDN的含义。
您能否确认Accept Method将逐个接受每个连接,这就是为什么我在服务器中看到来自不同Telnet会话的文本?
你能确认一下(我的服务器是一个C#库)我不能杀死我的服务器(使用这种代码)而不会杀死进程吗?它可以用线程,但稍后会出现。
如果我的代码出现问题,请帮助我:)
我将很快回来使用一个简单的多线程套接字服务器,但我不知道如何(我认为在使用线程或async / await之前一步可用)。
答案 0 :(得分:7)
首先,尽量不要学习这一点。如果您可以使用SignalR服务器,那么请执行此操作。 没有这样的东西就像&#34;简单&#34; TCP / IP级别的套接字服务器。
如果你坚持痛苦的路线(即学习正确的TCP / IP服务器设计),那么还有很多东西值得学习。首先,MSDN示例是众所周知的糟糕起点;它们几乎不能工作,往往不能处理任何类型的错误条件,这在现实世界中在TCP / IP级别工作时是绝对必要的。将它们视为如何调用方法的示例,不套接字客户端或服务器的示例。
我有TCP/IP FAQ可以帮助您,包括对backlog
parameter的说明。这是操作系统在您的代码接受它们之前代表您接受的连接数,并且它只是一个提示。
回答您的其他问题:对Accept
的单次呼叫将接受一个新的套接字连接。写入的代码具有无限循环,因此它将像任何其他无限循环一样工作;它将继续执行,直到遇到异常或其线程中止(在进程关闭时发生)。
如果我的代码出现问题,请帮帮我
哦,是的。这段代码有很多问题。毕竟,这是一个MSDN套接字示例。 :)脱离我的头顶:
Bind
显式使用环回地址。我想,可以玩,但请记住在现实世界中将其设置为IPAddress.Any
。backlog
参数可以进行测试,但在真实服务器上应为int.MaxValue
以启用现代服务器操作系统中的动态积压。catch
之后,并在Accept
/ Bind
失败后尝试Listen
。Listen
或Receive
),则整个服务器将关闭。请注意,被终止的客户端套接字将导致应被记录/忽略的异常,但它会停止此服务器。<EOF>
的情况下干净地关闭,那么服务器就会进入无限繁忙的循环。这是在简短的阅读之后。可能会有更多。