我想在.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