【发布时间】:2018-03-11 23:33:44
【问题描述】:
我输入了以下视频教程中的 C# 客户端/服务器课程...
C# Socket Programming - Multiple Clients
我使用 Visual Studio 2017 编译了该程序。
程序编译无误,可在单台计算机上运行。也就是说,如果我在同一台计算机上同时运行客户端和服务器,它们就可以正常连接。所以一切似乎都在工作。
但是,当我尝试将客户端和服务器放在家庭网络上的不同计算机上时,它们将无法连接。当安全防火墙询问时,我允许他们都拥有完全访问权限。
我不明白为什么将它们放在通过 WiFi 连接的同一个家庭网络上的不同计算机上时它们无法工作。计算机共享文件没有问题。
此外,在 YouTube 上的视频课程下方是已输入文件的链接。我什至将它们复制并粘贴到 Visual Studio 中并编译它们。但我得到完全相同的结果。它们在单台机器上编译和运行都很好,但我无法让它们在不同的机器上连接。
有什么想法吗?
我对只能连接到自身的计算机没有用处。
我做错了什么?
这里是硬拷贝客户端代码的链接:
这里是硬拷贝服务器代码的链接:
这是一个非常短的程序。
我不知道我做错了什么。我是否需要添加更多内容才能使其真正识别除自身以外的计算机?
客户端代码:
using System;
using System.Net.Sockets;
using System.Net;
using System.Text;
namespace MultiClient
{
class Program
{
private static readonly Socket ClientSocket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private const int PORT = 100;
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);
// Change IPAddress.Loopback to a remote IP to connect to a remote host.
ClientSocket.Connect(IPAddress.Loopback, 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 program.
/// </summary>
private static void Exit()
{
SendString("exit"); // Tell the server we are 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);
}
}
}
服务器代码:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace MultiServer
{
class Program
{
private static readonly Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private static readonly List<Socket> clientSockets = new List<Socket>();
private const int BUFFER_SIZE = 2048;
private const int PORT = 100;
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()
{
Console.WriteLine("Setting up server...");
serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT));
serverSocket.Listen(0);
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");
// Don't shutdown because the socket may be disposed and its disconnected anyway.
current.Close();
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);
}
}
}
注意:我认为代码可能还不错。我的问题很可能是权限问题?还是防火墙设置?或者我可能需要指定 IP 地址?
显然这个程序没有报告任何错误。它只是无法在同一网络上通过 WiFi 连接的两台笔记本电脑之间进行连接。
如果客户端和服务器在同一台计算机上运行,它就可以正常工作。但这没什么用。
【问题讨论】:
-
请花时间阅读How to Ask并发布minimal reproducible example。
-
如果您尝试从同一网络上的两台不同机器连接,您需要在客户端机器上指定 IP 地址(服务器机器)。另外请检查您的防火墙。 eg : ClientSocket.Connect("指定服务器IP", PORT);
标签: c# sockets client-server