android - 设备进入深度睡眠后套接字关闭 - Android Xamarin
问题描述
我创建了一个简单的 TCP 服务器,用于向 android 应用程序 (xamarin) 发送通知。
当应用程序处于前台时,它可以正常工作,但是当我在 1-3 分钟后使设备休眠(锁定设备)时,我收到一条错误消息 - “现有连接被远程主机强行关闭”,我输了联系。
我在 android 项目中创建了一个负责连接的服务。
测试服务器:
namespace AsyncServer
{
class Program
{
private static byte[] _buffer = new byte[2048];
private static List<connectedUser> Users = new List<connectedUser>();
private static Socket _serverSocket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private static int port = 25565;
static void Main(string[] args)
{
SetupServer();
while (true)
{
//Console.WriteLine("pick user name");
string userText = "User";// Console.ReadLine();
Console.WriteLine("Enter");
string re = Console.ReadLine();
string json = JsonConvert.SerializeObject(new NotificationOrderModel() { User = "Server", Name = re});
byte[] buffer = Encoding.UTF8.GetBytes(json);
if (Users != null)
{
foreach (connectedUser user in Users.ToList())
if (user.Name == userText)
Send(user, buffer);
}
}
}
private static void Send(connectedUser user , byte [] buff)
{
try
{
user._clientSocket.BeginSend(buff, 0, buff.Length, SocketFlags.None, new AsyncCallback(SendCallback), user._clientSocket);
}
catch (Exception)
{
Users.Remove(user);
}
}
private static void SetupServer()
{
Console.WriteLine("setting server");
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, port));
_serverSocket.Listen(5);
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
private static void AcceptCallback(IAsyncResult AR)
{
Socket socket = _serverSocket.EndAccept(AR);
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), _serverSocket);
}
private static void ReceiveCallback(IAsyncResult AR)
{
try
{
Socket socket = (Socket)AR.AsyncState;
int received = socket.EndReceive(AR);
if (received > 0)
{
byte[] dataBuf = new byte[received];
Array.Copy(_buffer, dataBuf, received);
string data = Encoding.UTF8.GetString(dataBuf);
var tmp = JsonConvert.DeserializeObject<NotificationOrderModel>(data);
if (Users != null)
{
bool flag = false;
foreach (connectedUser user in Users.ToList())
if (user._clientSocket == socket)
flag = true;
if (flag)
;
else
{
Users.Add(new connectedUser() { Name = tmp.User, _clientSocket = socket });
Console.WriteLine("connected - " + tmp.User); // to be removed
}
}
if (tmp.isPing)
{
string json = JsonConvert.SerializeObject(new NotificationOrderModel() { User = "Server", isPing = true });
if (Users != null)
{
foreach (connectedUser user in Users.ToList())
if (user.Name == tmp.User)
Send(user, dataBuf);
}
}
}
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
}
catch (SocketException ex)
{
//when user disconnects - closes the application
}
}
private static void SendCallback(IAsyncResult AR)
{
Socket socket = (Socket)AR.AsyncState;
socket.EndSend(AR);
}
}
class connectedUser
{
public string Name;
public Socket _clientSocket;
}
public class NotificationOrderModel //: OrderModel, ICloneable
{
public string Name;
public decimal Qty;
public string ServingPlace;
public string User;
public bool Seen = false;
public bool isPing = false;
public NotificationOrderModel()
{
}
}
}
Android中的套接字服务:
[Service]
[assembly: Dependency(typeof(SocketService))]
public class SocketService : Service
{
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Ping();
return StartCommandResult.Sticky;
}
public override void OnDestroy()
{
//if (_cts != null)
//{
// _cts.Token.ThrowIfCancellationRequested();
// _cts.Cancel();
//}
base.OnDestroy();
}
public static ObservableCollection<NotificationOrderModel> OrderList = new ObservableCollection<NotificationOrderModel>();
private static Socket _serverSocket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private static byte[] _buffer = new byte[2048];
private static string IP = App.Settings.ServerIP;
private const int port = 25565;
private static IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(IP), port);
public static bool Connected = false;
public static async Task<bool> Start()
{
if (!Connected)
{
//_serverSocket.ReceiveTimeout
_serverSocket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), _serverSocket);
if (_serverSocket.Connected == true)
Connected = true;
}
try
{
if (Connected == true)
{
// Console.ReadLine();
string json = JsonConvert.SerializeObject(new NotificationOrderModel() { User = App.DataProvider.User.Username, isPing = true });
byte[] data = Encoding.UTF8.GetBytes(json); //"test"
_serverSocket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), _serverSocket);
_serverSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), _serverSocket);
}
}
catch (Exception)
{
Connected = false;
}
return false;
}
//initiate
//ping
private static void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
//Console.Clear();
Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());
Connected = true;
}
catch (Exception e)
{
Thread.Sleep(200);
_serverSocket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), _serverSocket);
//Console.Clear();
Console.WriteLine("Attempting to connect");
}
}
private static void ReceiveCallback(IAsyncResult AR)
{
try
{
Socket socket = (Socket)AR.AsyncState;
int received = socket.EndReceive(AR);
if (received > 0)
{
byte[] dataBuf = new byte[received];
Array.Copy(_buffer, dataBuf, received);
string data = Encoding.UTF8.GetString(dataBuf);
var tmp = JsonConvert.DeserializeObject<NotificationOrderModel>(data);
if (!tmp.isPing)
{
OrderList.Add(tmp);
// DependencyService.Get<INotification>().CreateNotification("title", "text");
}
}
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
}
catch (SocketException ex)
{
//throw;
}
}
private static void SendCallback(IAsyncResult AR)
{
Socket socket = (Socket)AR.AsyncState;
socket.EndSend(AR);
}
private static async Task<bool> Initialized()
{
_serverSocket.ReceiveTimeout = -1;
_serverSocket.SendTimeout = -1;
_serverSocket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), _serverSocket);
try
{
Thread.Sleep(1000);
_serverSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), _serverSocket);
string json = JsonConvert.SerializeObject(new NotificationOrderModel() { User = App.DataProvider.User.Username, isPing = true });
byte[] data = Encoding.UTF8.GetBytes(json);
_serverSocket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), _serverSocket);
}
catch (SocketException ex)
{
Connected = false;
// _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ;
}
return true;
}
public static async Task<bool> Ping()
{
if (Connected != true)
return await Initialized();
else
{
try
{
string json = JsonConvert.SerializeObject(new NotificationOrderModel() { User = App.DataProvider.User.Username, isPing = true });
byte[] data = Encoding.UTF8.GetBytes(json);
_serverSocket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), _serverSocket);
}
catch (Exception)
{
Connected = false;
return false;
}
}
return false;
}
}
我用这个启动服务:
var intent = new Intent(this, typeof(SocketService));
StartService(intent);
解决方案
推荐阅读
- c - Realloc 现有数据正在丢失
- python - 如何在整个熊猫列上应用 json_normalize
- ruby-on-rails - 活动存储 - 带有 URL 或路径的原始文件扩展名
- c++ - 我如何从 C++ 中操作 csv
- i2c - 与 Wire.h(ESP32) 的 I2C 通信
- python-3.x - 我应该使用循环还是坚持使用嵌套的 if 语句?
- python - 如何使用数据框拆分新列中的两个 CSV 文件列,在熊猫中显示匹配项?
- c++ - C ++如何抛弃函数的虚拟性并调用基函数,而不是重写
- java - 块末尾的意外内容 - 是什么构建了损坏的流?
- python - 我如何获得水平小提琴图或箱线图?(在 hvplot 全息视图中默认为垂直)