gpt4 book ai didi

c# - Socket 编程 c#/客户端-服务器通信

转载 作者:行者123 更新时间:2023-12-03 12:04:36 26 4
gpt4 key购买 nike

我正在尝试在 .NET 中制作 2 个通过 Web 一起通信的程序(在控制台应用程序中)(代码来自您可以在下面找到的视频,我只是想让代码在适应它之前工作)。原谅我,我不是一个经验丰富的程序员。

我有一个服务器和一个客户端,当我在我的计算机(本地)上运行它们时它们可以完美地工作。
我可以将多个客户端连接到服务器,发送请求并获得响应。
当我在一台计算机上运行服务器并在另一台计算机上运行客户端并尝试通过互联网连接时,我遇到了这个问题。

我可以连接到服务器但无法通信,例如尝试请求时间时没有数据交换。我认为问题主要来自网络本身而不是代码。

这是服务器的代码:

class Program
{
private static Socket _serverSocket;
private static readonly List<Socket> _clientSockets = new List<Socket>();
private const int _BUFFER_SIZE = 2048;
private const int _PORT = 50114;
private static readonly byte[] _buffer = new byte[_BUFFER_SIZE];

static void Main()
{
Console.Title = "Server";
SetupServer();
Console.ReadLine(); // When we press enter close everything
CloseAllSockets();
}



private static void SetupServer()
{
// IPAddress addip = GetBroadcastAddress();
Console.WriteLine("Setting up server...");
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(new IPEndPoint(IPAddress.Any , _PORT));
_serverSocket.Listen(5);
_serverSocket.BeginAccept(AcceptCallback, null);
Console.WriteLine("Server setup complete");
}

/// <summary>
/// Close all connected client (we do not need to shutdown the server socket as its connections
/// are already closed with the clients)
/// </summary>
private static void CloseAllSockets()
{
foreach (Socket socket in _clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}

_serverSocket.Close();
}

private static void AcceptCallback(IAsyncResult AR)
{
Socket socket;

try
{
socket = _serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets)
{
return;
}

_clientSockets.Add(socket);
socket.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
Console.WriteLine("Client connected, waiting for request...");
_serverSocket.BeginAccept(AcceptCallback, null);
}

private static void ReceiveCallback(IAsyncResult AR)
{
Socket current = (Socket)AR.AsyncState;
int received;

try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
Console.WriteLine("Client forcefully disconnected");
current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway
_clientSockets.Remove(current);
return;
}

byte[] recBuf = new byte[received];
Array.Copy(_buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
Console.WriteLine("Received Text: " + text);

if (text.ToLower() == "get time") // Client requested time
{
Console.WriteLine("Text is a get time request");
byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
current.Send(data);
Console.WriteLine("Time sent to client");
}
else if (text.ToLower() == "exit") // Client wants to exit gracefully
{
// Always Shutdown before closing
current.Shutdown(SocketShutdown.Both);
current.Close();
_clientSockets.Remove(current);
Console.WriteLine("Client disconnected");
return;
}
else
{
Console.WriteLine("Text is an invalid request");
byte[] data = Encoding.ASCII.GetBytes("Invalid request");
current.Send(data);
Console.WriteLine("Warning Sent");
}

current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
}
}

这里是客户端代码:
class Program
{
private static readonly Socket _clientSocket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

private const int _PORT = 50114;

static void Main()
{
Console.Title = "Client";
ConnectToServer();
RequestLoop();
Exit();
}

private static void ConnectToServer()
{
int attempts = 0;

while (!_clientSocket.Connected)
{
try
{
attempts++;
Console.WriteLine("Connection attempt " + attempts);
_clientSocket.Connect("IpAddr", _PORT);
}
catch (SocketException)
{
Console.Clear();
}
}

Console.Clear();
Console.WriteLine("Connected");
}

private static void RequestLoop()
{
Console.WriteLine(@"<Type ""exit"" to properly disconnect client>");

while (true)
{
SendRequest();
ReceiveResponse();
}
}

/// <summary>
/// Close socket and exit app
/// </summary>
private static void Exit()
{
SendString("exit"); // Tell the server we re exiting
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
Environment.Exit(0);
}

private static void SendRequest()
{
Console.Write("Send a request: ");
string request = Console.ReadLine();
SendString(request);

if (request.ToLower() == "exit")
{
Exit();
}
}

/// <summary>
/// Sends a string to the server with ASCII encoding
/// </summary>
private static void SendString(string text)
{
byte[] buffer = Encoding.ASCII.GetBytes(text);
_clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
}

private static void ReceiveResponse()
{
var buffer = new byte[2048];
int received = _clientSocket.Receive(buffer, SocketFlags.None);
if (received == 0) return;
var data = new byte[received];
Array.Copy(buffer, data, received);
string text = Encoding.ASCII.GetString(data);
Console.WriteLine(text);
}
}
static void Main()
{
Console.Title = "Client";
ConnectToServer();
RequestLoop();
Exit();
}

private static void ConnectToServer()
{
int attempts = 0;

while (!_clientSocket.Connected)
{
try
{
attempts++;
Console.WriteLine("Connection attempt " + attempts);
_clientSocket.Connect("IpAddr", _PORT);
}
catch (SocketException)
{
Console.Clear();
}
}

Console.Clear();
Console.WriteLine("Connected");
}

“IpAddr”是路由器公共(public) IP 的占位符。

这是我当前代码基于的视频: https://www.youtube.com/watch?v=xgLRe7QV6QI

我直接从中获取了代码(您可以在描述中链接的站点上找到 2 个代码文件)。

我运行服务器,它等待连接。然后我运行尝试连接到服务器的客户端。我连接并在服务器上显示连接成功。然后客户端发送一个像“get time”这样的请求,服务器应该捕获它并做出响应:
 byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
current.Send(data);

回到网络端:

这是我尝试过的所有事情的列表,这是在寻找大约一整天的解决方案后导致问题的通常主要原因:
  • 我已经有一个用于路由器的静态公共(public) IP(所以公共(public) IP 永远不会改变)。尽管如此,我还是在 noip.com 上创建了一个动态 dns。
  • 我为运行服务器的计算机提供了静态租约,因此它始终具有相同的本地 IP。
  • 我在 Windows 防火墙中创建了规则,以确保我使用的端口已打开。我在试图通信的两台计算机上都这样做了。
  • 我转发了路由器上的端口,使其指向运行服务器的计算机的本地 IP。 (我尝试了很多不同的端口,没有机会)
  • 我尝试激活路由器上的“DMZ”,但很可能不是解决方案
  • 我试图创建一个 ASP.NET 网站,该网站的页面返回一个字符串,使用 IIS 7.5 发布它并进行设置。在本地主机上工作,但使用像“xx.xxx.xxx.xx:PORT/default/index”这样的公共(public) ip 我得到一个错误。然而,它在错误中显示了网站名称。此外,当使用计算机的本地 IP 时,它也不起作用(例如 192.168.1.180)。

  • 谢谢你的帮助。

    最佳答案

    我了解了消息框架,谢谢 CodeCaster。

    对于对此感到好奇的人,这是我发现的一个有趣的链接:http://blog.stephencleary.com/2009/04/message-framing.html

    但在尝试更改代码之前,我在 AWS vps 上运行了服务器,它立即运行,问题可能来自我的 isp 或路由器。我只是想知道它如何在不处理消息框架的情况下工作。

    关于c# - Socket 编程 c#/客户端-服务器通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33942783/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com