Socket Server in Windows Phone 8
从Windows Phone 8 开始,Socket 的支持扩大到允许开发者撰写Socket Server,也就是说,在不透过中介服务的情况下,开发者可以撰写一个Windows Phone Server Application来允许其它设备连入,
这在开发对战连线游戏时是个非常有用的机制。
文/黄忠成
Socket Support in Windows Phone 8
从Windows Phone 7.1开始便支持了Socket Programming,开发者可以直接使用Socket来开发需要快速通讯的网络应用程序,不过那时Socket仅支持到Client-Side,简单的说就是你无法在Windows Phone上建立一个Socket Server
来接入其它的Windows Phone App连线,必须透过一个由其它平台所提供的中介服务(像是Windows Client、网站等等),这大大的限制了Windows Phone Apps Socket的应用范围。
从Windows Phone 8 开始,Socket 的支持扩大到允许开发者撰写Socket Server,也就是说,在不透过中介服务的情况下,开发者可以撰写一个Windows Phone Server Application来允许其它设备连入,
这在开发对战连线游戏时是个非常有用的机制。
A Simple Socket Listener
用法很简单,你只需要利用StreamSocketListener来建立一个Server Socket,就可以接入来自其它设备的连线,如以下程序。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using SocketServer.Resources;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.Networking;
using Windows.Networking.Connectivity;
using System.Text;
namespace SocketServer
{
public class ListenInformation
{
public HostName Host { get; set; }
public string DisplayName { get; set; }
}
public partial class MainPage : PhoneApplicationPage
{
private StreamSocketListener _listener = new StreamSocketListener();
private List _ips = new List();
// Constructor
public MainPage()
{
InitializeComponent();
var hostNames = NetworkInformation.GetHostNames();
foreach (HostName hn in hostNames)
{
ListenInformation info = new ListenInformation() { Host = hn };
if (hn.IPInformation.NetworkAdapter.IanaInterfaceType == 71) //Wi-Fi
info.DisplayName = hn.CanonicalName + "(Wi-Fi)";
else if (hn.IPInformation.NetworkAdapter.IanaInterfaceType == 244) //cellular
info.DisplayName = hn.CanonicalName + "(cellular)";
else
info.DisplayName = hn.CanonicalName;
_ips.Add(info);
}
lstIPs.DisplayMemberPath = "DisplayName";
lstIPs.ItemsSource = _ips;
}
async private void WaitForData(StreamSocket socket)
{
var dr = new DataReader(socket.InputStream);
var dataReaded = await dr.LoadAsync(sizeof(uint));
if (dataReaded == 0)
return;
uint strLen = dr.ReadUInt32();
await dr.LoadAsync(strLen);
string msg = dr.ReadString(strLen);
if (msg.ToLower().Equals("bye"))
{
socket.Dispose();
return;
}
Dispatcher.BeginInvoke(() =>
{
lstOutput.Items.Add("recv:" + msg);
});
WaitForData(socket);
}
void listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
WaitForData(args.Socket);
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
if (lstIPs.SelectedItem != null)
{
((Button)sender).IsEnabled = false;
_listener.ConnectionReceived += listener_ConnectionReceived;
await _listener.BindEndpointAsync(((ListenInformation)lstIPs.SelectedItem).Host, "1067");
appTitle.Text = "listen on " + _listener.Information.LocalPort;
}
else
MessageBox.Show("please select a ip to listen.");
}
}
}
让我稍微解释一下这个程序几个关键片段。
public MainPage()
{
InitializeComponent();
var hostNames = NetworkInformation.GetHostNames();
foreach (HostName hn in hostNames)
{
ListenInformation info = new ListenInformation() { Host = hn };
if (hn.IPInformation.NetworkAdapter.IanaInterfaceType == 71) //Wi-Fi
info.DisplayName = hn.CanonicalName + "(Wi-Fi)";
else if (hn.IPInformation.NetworkAdapter.IanaInterfaceType == 244) //cellular
info.DisplayName = hn.CanonicalName + "(cellular)";
else
info.DisplayName = hn.CanonicalName;
_ips.Add(info);
}
lstIPs.DisplayMemberPath = "DisplayName";
lstIPs.ItemsSource = _ips;
}
理论上,每个Windows Phone 8设备应该都会有一个以上的网络位址,除非该设备没有数据连线及Wi-Fi,因此要起始一个Socket Server,得先决定要系结至哪个网络位址,这里透过GetHostNames()来取得所有可用的网络位址,
然后透过IanaInterfaceType来标示该网络位址的型态,一般来说, 71是Wi-Fi、244是数据连线。
private async void Button_Click(object sender, RoutedEventArgs e)
{
if (lstIPs.SelectedItem != null)
{
((Button)sender).IsEnabled = false;
_listener.ConnectionReceived += listener_ConnectionReceived;
await _listener.BindEndpointAsync(((ListenInformation)lstIPs.SelectedItem).Host, "1067");
appTitle.Text = "listen on " + _listener.Information.LocalPort;
}
else
MessageBox.Show("please select a ip to listen.");
}
当使用者选择了要系结的网络位址后,这里透过BindEndpointAsync来启用Socket Server,第一个参数是HostName,第二个则是要聆听的Port资讯。
当连线接入时,ConnectionReceived事件会触发,在此处透过DataReader来读入由Client端传入的数据。
async private void WaitForData(StreamSocket socket)
{
var dr = new DataReader(socket.InputStream);
var dataReaded = await dr.LoadAsync(sizeof(uint));
if (dataReaded == 0)
return;
uint strLen = dr.ReadUInt32();
await dr.LoadAsync(strLen);
string msg = dr.ReadString(strLen);
if (msg.ToLower().Equals("bye"))
{
socket.Dispose();
return;
}
Dispatcher.BeginInvoke(() =>
{
lstOutput.Items.Add("recv:" + msg);
});
WaitForData(socket);
}
void listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
WaitForData(args.Socket);
}
Client: Windows Phone 8
完成Server端后,Client端相对简单多了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using ClientSocketDemo.Resources;
using Windows.Networking.Sockets;
using Windows.Networking;
using Windows.Storage.Streams;
namespace ClientSocketDemo
{
public partial class MainPage : PhoneApplicationPage
{
private StreamSocket _socket = null;
// Constructor
public MainPage()
{
InitializeComponent();
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
_socket = new StreamSocket();
await _socket.ConnectAsync(new HostName(txtIP.Text), "1067");
((Button)sender).IsEnabled = false;
txtIP.IsEnabled = false;
btnSend.IsEnabled = true;
txtSendData.IsEnabled = true;
}
private async void btnSend_Click(object sender, RoutedEventArgs e)
{
DataWriter dr = new DataWriter(_socket.OutputStream);
string data = txtSendData.Text;
dr.WriteUInt32((uint)data.Length);
await dr.StoreAsync();
dr.WriteString(data);
await dr.StoreAsync();
dr.DetachStream();
}
}
}
透过ConnectAsync可以连接至Socket Server,第一个参数是HostName(IP),第二个是Port。
图1
Client: Windows 8 App
同理,你也可以撰写Windows Store App的客户端来连入Windows Phone。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace WinSocketClient
{
public sealed partial class MainPage : Page
{
private StreamSocket _socket = null;
public MainPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
_socket = new StreamSocket();
await _socket.ConnectAsync(new HostName(txtIP.Text), "1067");
((Button)sender).IsEnabled = false;
txtIP.IsEnabled = false;
btnSend.IsEnabled = true;
txtSendData.IsEnabled = true;
}
private async void btnSend_Click(object sender, RoutedEventArgs e)
{
DataWriter dr = new DataWriter(_socket.OutputStream);
string data = txtSendData.Text;
dr.WriteUInt32((uint)data.Length);
await dr.StoreAsync();
dr.WriteString(data);
await dr.StoreAsync();
dr.DetachStream();
}
}
}
图2
原文:大专栏 Socket Server in Windows Phone 8
原文地址:https://www.cnblogs.com/chinatrump/p/11516562.html
- android 向webview传值
- 用搜索神器Everything定位Webshell木马后门
- 终端图像处理系列 - OpenGL ES 2.0 - 3D基础(矩阵投影)
- XssHtml – 基于白名单的富文本XSS过滤类
- fireeyee解剖新型Android恶意软件
- WordPress系统暴力破解测试工具 – wpbf
- RecyclerView notifyItem闪烁的问题
- 独家: iOS是如何收集用户的地理信息的
- Hygieia 为何物?DevOps 利器也
- 汽车攻击离你很近:一分钟变成汽车黑客
- LIFX智能灯泡漏洞泄露WIFI密码
- android ViewPager+Fragment之懒加载
- 逆向APK进行smali注入实现“秒破WIFI”
- 我所理解的Android 启动模式
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- RecyclerView实现纵向和横向滚动
- Android ListView列表视图的使用方法
- 滴滴自动化运维平台夜莺实战部署
- Android UI使用HorizontalListView实现水平滑动
- python操作yaml说明
- python由已知数组快速生成新数组的方法
- Git 修改已提交 commit 的信息
- 解决windows下python3使用multiprocessing.Pool出现的问题
- 解决pyqt5异常退出无提示信息的问题
- TensorFlow2.1.0安装过程中setuptools、wrapt等相关错误指南
- 来来来,让咱重新认识一下算法的复杂度!
- 带你通过字节跳动面试---操作系统复习
- Java 8 中的接口和抽象类到底有啥区别?
- Android自定义View实现简单炫酷的球体进度球实例代码
- 详解android 中文字体向上偏移解决方案