我想在.NET中通过网络进行通信(代码是来自一个视频,你可以在下面找到,我只是试图让2个程序(在控制台应用程序中)使代码在适应它之前工作)。原谅我,我不是一个有经验的程序员。Socket编程c#/客户端 - 服务器通信
我有一台服务器和一个客户端,当我在我的计算机(本地)上运行它们时,它们都能够完美地工作。 我可以连接多个客户端到服务器,发送请求并获得响应。 当我在计算机上运行服务器并在另一台计算机上运行客户端时,我遇到了问题,并尝试通过Internet进行连接。
我可以连接到服务器,但通信不起作用,当试图请求时间作为示例时没有数据交换。我认为问题主要来自网络本身而不是代码。
下面是该服务器的代码:
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” 是路由器的公网IP的占位符。
这是视频我当前的代码是基于:https://www.youtube.com/watch?v=xgLRe7QV6QI
我直接把代码从它(你可以找到在说明链接的网站上的2个代码文件)。
我运行服务器,它等待连接。然后我运行试图连接到服务器的客户端。我连接并在服务器上显示成功的连接。然后,客户机发出像“获取时间”的请求,服务器应该抓住它,并作出回应:
byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
current.Send(data);
返回到网络侧:
这是所有我已经试过了事情的清单,这是问题的通常的主要原因寻找一个解决方案约一整天后:
我已经有一个静态公网IP的路由器(因此公众IP永远不会改变)。尽管如此,我在noip.com上创建了一个动态DNS。
我给服务器运行的计算机提供了一个静态租约,所以它总是有相同的本地ip。
我在Windows防火墙中创建了规则,以确保打开我使用的端口。我在两台试图通信的计算机上都这样做了。
我转发了路由器上的端口,以便它指向运行服务器的计算机的本地ip。 (我尝试了很多不同的端口,没有机会)
我试过在路由器上启动“DMZ”,但它是最有可能不是一个解决方案
我试图创建一个ASP.NET网站,页面返回一个字符串,使用IIS 7.5发布并进行设置。在本地主机上工作,但使用公共IP,如“xx.xxx.xxx.xx:PORT/default/index”我收到一个错误。但它显示错误中的网站名称。此外,当使用计算机的本地IP时,它也不起作用(类似于192.168.1.180)。
感谢您的帮助。
不要从YouTube学习代码,购买一本书。这个例子被打破了,这是浪费时间。它没有实现协议,所以你的服务器永远不会收到“获取时间”,它在一个数据包中收到“get t”,而在另一个数据包中收到“ime”。例如。至少,这是我在快速跳过视频时看到的。如果您需要帮助调试您的代码,请在您的问题中包含所有**相关**代码。 :)连接代码是无关紧要的,否则你会得到一个你无法连接的异常。错误出现在处理数据发送和接收的代码中。 – CodeCaster
它在本地工作,我不需要任何调试,我花了很多时间在网上找到解决方案,所以我只是在这里发布我的问题^^。 –
_“它在我的机器上运行”_是破解网络代码的经典借口,但这并不能使它更少受到破坏。如果可以连接,但通信无法按预期工作,则代码不起作用。我当然不想惹恼你,但是这些教程每天会产生多个这样的问题。请在您的问题中包含代码。 – CodeCaster