我正在尝试在具有Win 10 IoT的Raspberry Pi 3和由Xamarin Android开发的App之间开发一个简单的TCP服务器/客户端。 我正在使用我的Samsung S9 +调试应用程序。 服务器是Raspberry。
在Raspberry中,我输入了以下代码:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.StartServer();
}
private async void StartServer()
{
try
{
//Create a StreamSocketListener to start
//listening for TCP connections.
Windows.Networking.Sockets.StreamSocketListener socketListener = new Windows.Networking.Sockets.StreamSocketListener();
//Hook up an event handler to call when connections are received.
socketListener.ConnectionReceived += SocketListener_ConnectionReceived;
//Start listening for incoming TCP connections on the specified port. You can specify any port that's not currently in use.
await socketListener.BindEndpointAsync(new Windows.Networking.HostName("localhost"),"9999");
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
private async void socketListener_ConnectionReceived(Windows.Networking.Sockets.StreamSocketListener sender, Windows.Networking.Sockets.StreamSocketListenerConnectionReceivedEventArgs args)
{
//Read line from the remote client.
Stream inStream = args.Socket.InputStream.AsStreamForRead();
StreamReader reader = new StreamReader(inStream);
string request = await reader.ReadLineAsync();
//Send the line back to the remote client.
Stream outStream = args.Socket.OutputStream.AsStreamForWrite();
StreamWriter writer = new StreamWriter(outStream);
await writer.WriteLineAsync(request);
await writer.FlushAsync();
}
在Xamarin App中,我有这个:
public class MainActivity : AppCompatActivity
{
EditText txtInvia;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
Button btnInvia = FindViewById<Button>(Resource.Id.btnInvia);
Button btnConnetti = FindViewById<Button>(Resource.Id.btnConnetti);
txtInvia = FindViewById<EditText>(Resource.Id.txtInvia);
btnConnetti.Click += BtnConnetti_Click;
btnInvia.Click += BtnInvia_Click;
}
private void BtnInvia_Click(object sender, EventArgs e)
{
}
private void BtnConnetti_Click(object sender, EventArgs e)
{
this.StartClient();
}
public static bool PING(string ipAddress)
{
// Ping's the local machine.
Ping pingSender = new Ping();
IPAddress address = IPAddress.Parse(ipAddress);
PingReply reply = pingSender.Send(address);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address.ToString());
Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
return true;
}
else
{
Console.WriteLine(reply.Status);
return false;
}
}
private const int PortNumber = 9999;
private void StartClient()
{
string localAddr = "192.168.137.1";
if (PING(localAddr))
{
try
{
MyClientTask myClientTask = new MyClientTask(localAddr, PortNumber, string.Format(txtInvia.Text + "\r\n"));
myClientTask.Execute();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
MyClientTask在哪里:
public class MyClientTask : AsyncTask
{
string dstAddress;
int dstPort;
string response = "";
string msgToServer;
public MyClientTask(string addr, int port, string msgTo)
{
dstAddress = addr;
dstPort = port;
msgToServer = msgTo;
}
protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params)
{
Socket socket = null;
DataOutputStream dataOutputStream = null;
try
{
socket = new Socket(dstAddress, dstPort);
dataOutputStream = new DataOutputStream(socket.OutputStream);
if (msgToServer != null)
{
dataOutputStream.WriteBytes(msgToServer);
}
ByteArrayOutputStream byteArrayOutputStream =
new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
System.IO.Stream inputStream = socket.InputStream;
/*
* notice:
* inputStream.read() will block if no data return
*/
while ((bytesRead = inputStream.Read(buffer)) != -1)
{
byteArrayOutputStream.Write(buffer, 0, bytesRead);
response += byteArrayOutputStream.ToString("UTF-8");
}
}
catch (UnknownHostException e)
{
// TODO Auto-generated catch block
e.PrintStackTrace();
response = "UnknownHostException: " + e.ToString();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.PrintStackTrace();
response = "IOException: " + e.ToString();
}
finally
{
if (socket != null)
{
try
{
socket.Close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.PrintStackTrace();
}
}
}
return null;
}
}
在MyClientTask中,我使用以下指令创建新套接字:
socket = new Socket(dstAddress, dstPort);
如果我将手机连接到Raspberry创建的HotSpot,则会收到此错误
IOException: Java.Net.ConnectException: failed to connect to /192.168.137.175 (port 9999) from /:: (port 37604): connect failed: ECONNREFUSED (Connection refused) ---> Android.Systems.ErrnoException: connect failed: ECONNREFUSED (Connection refused)
如果我在同一路由器上通过以太网将手机连接到WiFi和Raspberry,则Xamarin App会因为超时而无法创建套接字。
我做错了什么? 谢谢! <3
编辑: 我发现应用程序中Raspberry的IP地址是错误的,所以现在是正确的,我的应用程序被阻止的方式与以太网连接相同。
答案 0 :(得分:0)
首先,您可以使用 BindServiceNameAsync 方法而不是 BindEndpointAsync 方法,以将流量限制为地址或适配器。
第二,您需要为使用的服务器端口设置防火墙阻止,以下命令可以允许访问。
netsh advfirewall firewall add rule name="Tcp Server Port(9999)" dir=in protocol=TCP localport=9999 action=Allow
最后,您需要指定应用程序的device capabilities。应该为Tcp服务器启用Private Networks (Client & Server)
功能。
您可以参考一个StreamSocket示例here。它显示了如何使用StreamSocketListener类创建TCP套接字以侦听传入的TCP连接。