我创建了一个简单的客户端/服务器程序,它从客户端获取输入并通过查看文本文件以查看是否存在与输入关联的答案来返回对输入的答案。
我遇到的问题是我在服务器端得到了响应,但我不知道如何将它发送回客户端(它只是在客户端返回输入)。
第二个问题是它将执行一次,因为它只会接受一个输入。我尝试添加一个循环,但无法使其正常工作。
服务器.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace server
{
class server
{
const string SERVER_IP = "127.0.0.1";
static void Main(string[] args)
{
//Create Dictionary
Dictionary<string, string> dict = new Dictionary<string, string>();
//---Read Text File containing commands ---
StreamReader sr = new StreamReader(@"C:\Users\Desktop\potato.txt");
string line;
//Splits the text into commands:responses
while ((line = sr.ReadLine()) != null)
{
string[] arr = line.Split(';');
dict.Add(arr[0], arr[1]);
}
//Print dictionary TESTING FUNCTION
foreach (KeyValuePair<string, string> kvp in dict)
{
Console.WriteLine("Command = {0} Response = {1}", kvp.Key, kvp.Value);
}
//---Input the port number for clients to conect---
Console.Write("Input port" + System.Environment.NewLine);
int PORT_NO = int.Parse(Console.ReadLine());
//---listen at the specified IP and port no.---
IPAddress localAdd = IPAddress.Parse(SERVER_IP);
TcpListener listener = new TcpListener(localAdd, PORT_NO);
Console.WriteLine("Listening for Commands");
listener.Start();
//---incoming client connected---
TcpClient client = listener.AcceptTcpClient();
//---get the incoming data through a network stream---
NetworkStream nwStream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
//---read incoming stream---
int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);
//---convert the command data received into a string---
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received Command : " + dataReceived);
//---Search Command and send a response
string Response;
if (dict.TryGetValue(dataReceived, out Response))
{
Console.WriteLine(Response);
}
//---write back the response to the client---
Console.WriteLine("Sending Response : " + Response);
nwStream.Write(buffer, 0, bytesRead);
Console.ReadLine();
}
}
}
最佳答案
您需要将 Response
转换为 byte[]
,就像您在发送请求的客户端中所做的那样(即 bytesToSend
)。例如:
Console.WriteLine("Sending Response : " + Response);
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(Response);
nwStream.Write(bytesToSend, 0, bytesToSend.Length);
Console.ReadLine();
就是说,如果没有先阅读有关 TCP 和套接字的引用资料就尝试编写 TCP 代码,您犯了每个人都会犯的典型错误:您错误地认为,当您从套接字读取时,您总是会在每次操作中收到读取的字节。因此,即使使用上述修复(它确实解决了 服务器 端的问题),您也可能会在客户端看到部分响应(在本地测试时不太可能,但如果你转向在 Internet 上或跨 LAN 运行,尤其是随着消息大小的增加)。
对于低容量网络交互,您可能需要考虑使用 StreamReader
和 StreamWriter
对象包装您的 NetworkStream
,并使用 ReadLine()
和 WriteLine()
接收和发送数据(即使用换行符作为数据的分隔符)。
至于处理多个请求,根据您在此处提供的代码,最简单的方法是在 listener.Start()
之后的服务器代码周围添加一个循环> 方法。 IE。包含该语句之后的所有代码,从调用 listener.AcceptTcpClient()
开始,一直到方法中的最后一条语句。然而,这同样只适用于少量网络代码。如果您预计客户端将需要您的服务器处理多个请求,尤其是快速连续的请求,那么您真正想要的是让客户端保持连接,即只连接一次,然后让它在同一个连接上发送多个请求。
同样,如果您希望能够同时处理多个客户端,则不能在单个线程中运行服务器。相反,至少您需要使用您现在正在使用的线程阻塞逻辑,其中您为每个客户端创建了一个新线程。更好的方法是使用非阻塞 API(例如 NetworkStream.BeginRead()
、StreamReader.ReadLineAsync()
等……有许多异步选项可供选择),让 .NET 为您处理线程。
这样做需要对服务器代码进行重大更改。您确实应该仔细查看 MSDN 和 Stack Overflow 上的各种示例,了解此类事情是如何完成的。我还强烈建议您通读 Winsock Programmer's FAQ .它根本不是专门针对 .NET 的,但确实涵盖了您需要了解的所有关键细节,以便有效且正确地使用 .NET API。
关于C# 客户端/服务器从服务器返回应答给客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37287995/