だから、私は基本的にサーバーとクライアントを持っています。
サーバーは.NETCore 2.2コンソールアプリケーションであり、接続が開かれると、着信接続をリッスンし、要求を読み取り、MySQL DBからデータを取得して、クライアントに送り返します。
クライアントはXamarinFormsアプリケーションであり、これらのリクエストをサーバーに送信します。それほど複雑なことはありません。
これで、ローカルのWindowsマシンでサーバーを実行すると、割り当てられたポートのリッスンが開始され、要求を正しく受け入れて応答を送信します。ただし、このサーバーアプリを実行することを目的としたUbuntu 19.04マシンにデプロイすると、着信接続が表示されません。
もちろん、これがネットワークの問題ではないことを確認しnc -l PORT
、関連するポートをnetcat()しようとしましたが、正しいデータを受信しています。
これが私のサーバーコードです:
public static class Server
{
public static Dictionary<string, Session> Sessions { get; private set; } = new Dictionary<string, Session>();
public static int Main(string[] args)
{
return RunServer();
}
private static int RunServer()
{
var listener = new TcpListener(IPAddress.Loopback, ServerConfig.Port);
int errorCode = 0;
try
{
listener.Start();
Console.WriteLine("Server running - listening to " + ServerConfig.Port + " ..."); // this is printed in Ubuntu
while (true)
{
var clientTask = listener.AcceptTcpClientAsync();
if (clientTask.Result != null)
{
using (TcpClient tcpClient = clientTask.Result)
{
// This line is printed in Windows/localhost, but not on the Ubuntu production machine
Console.WriteLine("Connected to {0}", (tcpClient.Client.RemoteEndPoint as IPEndPoint).Address);
string data;
string cmd;
string[] parameters;
string response = null;
NetworkStream stream = tcpClient.GetStream();
data = ReceiveRemoteMessage(stream); // See below
if (string.IsNullOrWhiteSpace(data))
continue;
parameters = data.Split(' ');
cmd = parameters[0];
try
{
// Note: the CommunicationManager class that actually processes the requests is not relevant to this question, so it's not included
string methodName = "Manage" + cmd + "Request";
var argList = new List<object>();
var i = 0;
foreach(object par in parameters)
{
i++;
if (i == 1)
continue;
argList.Add(par);
}
object[] args = argList.ToArray();
response = (string) typeof(CommunicationManager).GetMethod(methodName).Invoke(null, args);
}
catch (Exception e)
{
if (e is AmbiguousMatchException ||
e is ArgumentNullException ||
e is TargetException ||
e is ArgumentException ||
e is TargetInvocationException ||
e is TargetParameterCountException ||
e is MethodAccessException ||
e is InvalidOperationException ||
e is NotSupportedException)
{
response = ServerResponse.InvalidRequest; // ServerResponse is a static class with read-only static string fields
}
else
{
response = ServerResponse.GenericException;
}
}
if (!string.IsNullOrWhiteSpace(response))
{
SendSocketMessage(stream, response);
}
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
errorCode = 1;
}
finally
{
listener.Stop();
}
Console.WriteLine($"\nExit code: {errorCode}\nPress any key to terminate.");
Console.ReadKey();
return errorCode;
}
private static void SendSocketMessage(NetworkStream stream, string message)
{
var encryptedMsg = Encrypt.EncryptString(message);
stream.Write(Encoding.UTF8.GetBytes(encryptedMsg));
}
private static string ReceiveRemoteMessage(NetworkStream stream)
{
const int bufferSize = 1024;
byte[] bytes;
string data = string.Empty;
while (true)
{
bytes = new byte[bufferSize];
int bytesReceived = stream.Read(bytes);
string utfString = Encoding.UTF8.GetString(bytes, 0, bytesReceived);
if (string.IsNullOrEmpty(utfString))
break;
data += utfString;
if (bytesReceived < bufferSize)
break;
}
var decryptedMsg = Encrypt.DecryptString(data);
return decryptedMsg;
}
}
これは、Xamarin(Mono)で使用される私のクライアントコードです。
public static string SendServerRequest(string request)
{
//
try
{
TcpClient client = new TcpClient();
client.ConnectAsync(ServerConfig.Hostname, ServerConfig.Port).Wait();
NetworkStream stream = client.GetStream();
var encryptedRequest = Encrypt.EncryptString(request);
var sentBytes = Encoding.UTF8.GetBytes(encryptedRequest);
stream.Write(sentBytes, 0, sentBytes.Length);
const int bufferSize = 1024;
byte[] bytes;
string data = string.Empty;
int totalBytesReceived = 0;
while (true)
{
bytes = new byte[bufferSize];
int bytesReceived = stream.Read(bytes, totalBytesReceived, bufferSize);
totalBytesReceived += bytesReceived;
string utfString = Encoding.UTF8.GetString(bytes, 0, bytesReceived);
if (string.IsNullOrEmpty(utfString))
break;
data += utfString;
if (bytesReceived < bufferSize)
break;
}
return Encrypt.DecryptString(data);
}
catch
{
return null;
}
}
ありがとう。
var listener = new TcpListener(IPAddress.Loopback, ServerConfig.Port);
これは、TcpListenerがループバックアドレス(のみ)をリッスンする必要があることを示しています。つまり、サーバーは、ネットワーク上の他のマシンではなく、ローカルマシンからのみ発信される着信接続をリッスンする必要があります。
私はあなたが欲しいと思いますIPAddress.Any
:
var listener = new TcpListener(IPAddress.Any, ServerConfig.Port);
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加