重新想象 Windows 8 Store Apps (62) - 通信: Socket TCP, Socket UDP
作者:webabcd
介绍
重新想象 Windows 8 Store Apps 之 通信
- Socket - Tcp Demo
- Socket - 实现一个自定义的 http server
- Socket - Udp Demo
示例
1、演示 socket tcp 的应用(本例既做服务端又做客户端)
Communication/Socket/TcpDemo.xaml
<Page
x:Class="XamlDemo.Communication.Socket.TcpDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlDemo.Communication.Socket"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="Transparent">
<StackPanel Margin="120 0 0 0" Orientation="Horizontal"> <StackPanel>
<Button Name="btnStartListener" Content="start a socket listener" Click="btnStartListener_Click" />
<Button Name="btnConnectListener" Content="connect to the socket listener" Click="btnConnectListener_Click" Margin="0 10 0 0" />
<Button Name="btnSendData" Content="send data" Click="btnSendData_Click" Margin="0 10 0 0" />
<Button Name="btnCloseSocket" Content="close server socket and client socket" Click="btnCloseSocket_Click" Margin="0 10 0 0" />
</StackPanel> <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" Margin="20 0 0 0" /> </StackPanel>
</Grid>
</Page>
Communication/Socket/TcpDemo.xaml.cs
/*
* 演示 socket tcp 的应用(本例既做服务端又做客户端)
*
* 通过 StreamSocketListener 实现 tcp 通信的服务端的 socket 监听
* 通过 StreamSocket 实现 tcp 通信的客户端 socket
*
* 注:需要在 Package.appxmanifest 中增加配置 <Capability Name="privateNetworkClientServer" />
*/ using System;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; namespace XamlDemo.Communication.Socket
{
public sealed partial class TcpDemo : Page
{
/// <summary>
/// 服务端 socket
/// </summary>
private StreamSocketListener _listener; /// <summary>
/// 客户端 socket
/// </summary>
private StreamSocket _client; /// <summary>
/// 客户端向服务端发送数据时的 DataWriter
/// </summary>
private DataWriter _writer; public TcpDemo()
{
this.InitializeComponent();
} // 在服务端启动一个 socket 监听
private async void btnStartListener_Click(object sender, RoutedEventArgs e)
{
// 实例化一个 socket 监听对象
_listener = new StreamSocketListener();
// 监听在接收到一个连接后所触发的事件
_listener.ConnectionReceived += _listener_ConnectionReceived; try
{
// 在指定的端口上启动 socket 监听
await _listener.BindServiceNameAsync(""); lblMsg.Text += "已经在本机的 2211 端口启动了 socket(tcp) 监听";
lblMsg.Text += Environment.NewLine; }
catch (Exception ex)
{
SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString();
lblMsg.Text += Environment.NewLine;
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} // socket 监听接收到一个连接后
async void _listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
// 实例化一个 DataReader,用于读取数据
DataReader reader = new DataReader(args.Socket.InputStream); await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
lblMsg.Text += "服务端收到了来自: " + args.Socket.Information.RemoteHostName.RawName + ":" + args.Socket.Information.RemotePort + " 的 socket 连接";
lblMsg.Text += Environment.NewLine;
}); try
{
while (true)
{
// 自定义协议(header|body):前4个字节代表实际数据的长度,之后的实际数据为一个字符串数据 // 读取 header
uint sizeFieldCount = await reader.LoadAsync(sizeof(uint));
if (sizeFieldCount != sizeof(uint))
{
// 在获取到合法数据之前,socket 关闭了
return;
} // 读取 body
uint stringLength = reader.ReadUInt32();
uint actualStringLength = await reader.LoadAsync(stringLength);
if (stringLength != actualStringLength)
{
// 在获取到合法数据之前,socket 关闭了
return;
} await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// 显示客户端发送过来的数据
lblMsg.Text += "接收到数据: " + reader.ReadString(actualStringLength);
lblMsg.Text += Environment.NewLine;
});
}
}
catch (Exception ex)
{
var ignore = this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString();
lblMsg.Text += Environment.NewLine;
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
});
}
} // 创建一个客户端 socket,并连接到服务端 socket
private async void btnConnectListener_Click(object sender, RoutedEventArgs e)
{
HostName hostName;
try
{
hostName = new HostName("127.0.0.1");
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine; return;
} // 实例化一个客户端 socket 对象
_client = new StreamSocket(); try
{
// 连接到指定的服务端 socket
await _client.ConnectAsync(hostName, ""); lblMsg.Text += "已经连接上了 127.0.0.1:2211";
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString();
lblMsg.Text += Environment.NewLine;
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} // 从客户端 socket 发送一个字符串数据到服务端 socket
private async void btnSendData_Click(object sender, RoutedEventArgs e)
{
// 实例化一个 DataWriter,用于发送数据
if (_writer == null)
_writer = new DataWriter(_client.OutputStream); // 自定义协议(header|body):前4个字节代表实际数据的长度,之后的实际数据为一个字符串数据 string data = "hello webabcd " + DateTime.Now.ToString("hh:mm:ss");
_writer.WriteUInt32(_writer.MeasureString(data)); // 写 header 数据
_writer.WriteString(data); // 写 body 数据 try
{
// 发送数据
await _writer.StoreAsync(); lblMsg.Text += "数据已发送: " + data;
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString();
lblMsg.Text += Environment.NewLine;
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} // 关闭客户端 socket 和服务端 socket
private void btnCloseSocket_Click(object sender, RoutedEventArgs e)
{
try
{
_writer.DetachStream(); // 分离 DataWriter 与 Stream 的关联
_writer.Dispose(); _client.Dispose();
_listener.Dispose(); lblMsg.Text += "服务端 socket 和客户端 socket 都关闭了";
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
}
}
}
2、演示 socket 的应用(演示如何实现一个 http server,需要注意的是此 http server 只能在此 app 内部调用,而不能在外部调用)
Communication/Socket/CustomHttpServer.xaml
<Page
x:Class="XamlDemo.Communication.Socket.CustomHttpServer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlDemo.Communication.Socket"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="Transparent">
<StackPanel Margin="120 0 0 0" Orientation="Horizontal"> <StackPanel>
<Button Name="btnLaunchHttpServer" Content="启动 http server" Click="btnLaunchHttpServer_Click" />
<Button Name="btnRequestHttpServer" Content="请求 http server" Click="btnRequestHttpServer_Click" Margin="0 10 0 0" />
<Button Name="btnCloseHttpServer" Content="关闭 http server" Click="btnCloseHttpServer_Click" Margin="0 10 0 0" />
</StackPanel> <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" Margin="20 0 0 0" /> </StackPanel>
</Grid>
</Page>
Communication/Socket/CustomHttpServer.xaml.cs
/*
* 演示 socket 的应用(演示如何实现一个 http server,需要注意的是此 http server 只能在此 app 内部调用,而不能在外部调用)
*
* 注:需要在 Package.appxmanifest 中增加配置 <Capability Name="privateNetworkClientServer" />
*/ using System;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using System.Text;
using System.Net.Http; namespace XamlDemo.Communication.Socket
{
public sealed partial class CustomHttpServer : Page
{
/// <summary>
/// http server 的 socket
/// </summary>
private StreamSocketListener _listener; public CustomHttpServer()
{
this.InitializeComponent();
} // 启动 http server,即在服务端启动一个 socket 监听
private async void btnLaunchHttpServer_Click(object sender, RoutedEventArgs e)
{
// 实例化一个 socket 监听对象
_listener = new StreamSocketListener();
// 监听在接收到一个连接后所触发的事件
_listener.ConnectionReceived += _listener_ConnectionReceived; try
{
// 在指定的端口上启动 socket 监听
await _listener.BindServiceNameAsync(""); lblMsg.Text += "已经在本机的 2212 端口启动了 socket 监听,即 http server 的地址为:http://localhost:2212/";
lblMsg.Text += Environment.NewLine; }
catch (Exception ex)
{
SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString();
lblMsg.Text += Environment.NewLine;
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} // socket 监听接收到一个连接后,即收到一个 http 请求后
async void _listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
// 实例化一个 DataReader,用于读取数据
DataReader reader = new DataReader(args.Socket.InputStream); try
{
// 用于保存 http 请求的 header
StringBuilder sb = new StringBuilder();
while (true)
{
// 一个字节一个字节地读
uint loaded = await reader.LoadAsync();
if (loaded != )
return; char c = (char)reader.ReadByte();
sb.Append(c); // 碰到 \r\n\r\n 则说明已经完整地获取了 header 信息
if (sb.ToString().IndexOf("\r\n\r\n") > )
{
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
lblMsg.Text += "接收到的 http request header: ";
lblMsg.Text += Environment.NewLine;
lblMsg.Text += sb.ToString();
lblMsg.Text += Environment.NewLine;
}); // 用于保存 http 响应的数据
string response = ""; // 响应的 http 头信息
response += "HTTP/1.1 200 OK";
response += "Content-Type:text/html\r\n";
response += "Server:Custom Http Server\r\n";
response += "Content-Length:2\r\n";
response += "Connection: Keep-Alive\r\n\r\n"; // 头信息以 \r\n\r\n 结尾 // 响应的内容
response += "ok"; // 将已经构造好的数据响应给客户端
DataWriter writer = new DataWriter(args.Socket.OutputStream);
writer.WriteString(response);
await writer.StoreAsync(); sb.Clear();
}
}
}
catch (Exception ex)
{
var ignore = this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString();
lblMsg.Text += Environment.NewLine;
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
});
}
} private async void btnRequestHttpServer_Click(object sender, RoutedEventArgs e)
{
HttpClient client = new HttpClient();
// 请求 http server
string result = await client.GetStringAsync(new Uri("http://localhost:2212/abc.html")); // 输出 http server 的响应结果
lblMsg.Text += "response: " + result;
lblMsg.Text += Environment.NewLine; } // 关闭 http server,即关闭服务端 socket
private void btnCloseHttpServer_Click(object sender, RoutedEventArgs e)
{
try
{
_listener.Dispose(); lblMsg.Text += "http server 关闭了";
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
}
}
}
3、演示 socket udp 的应用(本例既做服务端又做客户端)
Communication/Socket/UdpDemo.xaml
<Page
x:Class="XamlDemo.Communication.Socket.UdpDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlDemo.Communication.Socket"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="Transparent">
<StackPanel Margin="120 0 0 0" Orientation="Horizontal"> <StackPanel>
<Button Name="btnStartListener" Content="start a socket listener" Click="btnStartListener_Click" />
<Button Name="btnSendData" Content="send data" Click="btnSendData_Click" Margin="0 10 0 0" />
<Button Name="btnCloseSocket" Content="close server socket and client socket" Click="btnCloseSocket_Click" Margin="0 10 0 0" />
</StackPanel> <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" Margin="20 0 0 0" /> </StackPanel>
</Grid>
</Page>
Communication/Socket/UdpDemo.xaml.cs
/*
* 演示 socket udp 的应用(本例既做服务端又做客户端)
*
* 通过 DatagramSocket 来实现 udp 通信的服务端和客户端
*
* 注:需要在 Package.appxmanifest 中增加配置 <Capability Name="privateNetworkClientServer" />
* 注:udp 报文(Datagram)的最大长度为 65535(包括报文头)
*/ using System;
using System.Threading;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; namespace XamlDemo.Communication.Socket
{
public sealed partial class UdpDemo : Page
{
/// <summary>
/// 服务端 socket
/// </summary>
private DatagramSocket _listener; /// <summary>
/// 客户端 socket
/// </summary>
private DatagramSocket _client; /// <summary>
/// 客户端向服务端发送数据时的 DataWriter
/// </summary>
private DataWriter _writer; public UdpDemo()
{
this.InitializeComponent();
} // 在服务端启动一个 socket 监听
private async void btnStartListener_Click(object sender, RoutedEventArgs e)
{
// 实例化一个 socket 监听对象
_listener = new DatagramSocket();
// 服务端监听在接收到信息后所触发的事件
_listener.MessageReceived += _listener_MessageReceived; try
{
// 在指定的端口上启动 socket 监听
await _listener.BindServiceNameAsync(""); lblMsg.Text += "已经在本机的 2213 端口启动了 socket(udp) 监听";
lblMsg.Text += Environment.NewLine; }
catch (Exception ex)
{
SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString();
lblMsg.Text += Environment.NewLine;
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} // 服务端的 socket udp 监听接收到信息后
private void _listener_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
try
{
// 输出接收到的数据
DataReader dataReader = args.GetDataReader();
uint stringLength = dataReader.UnconsumedBufferLength;
var ignore = this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
lblMsg.Text += "接收到数据: " + dataReader.ReadString(stringLength) + " - 数据来自: " + args.RemoteAddress.RawName + ":" + args.RemotePort;
lblMsg.Text += Environment.NewLine;
});
}
catch (Exception ex)
{
SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString();
lblMsg.Text += Environment.NewLine;
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} // 从客户端 socket 发送数据到服务端 socket
private async void btnSendData_Click(object sender, RoutedEventArgs e)
{
if (_client == null)
{
HostName hostName;
try
{
hostName = new HostName("127.0.0.1");
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine; return;
} try
{
// 实例化客户端 DatagramSocket,并准备往 127.0.0.1:2213 发送数据
_client = new DatagramSocket();
await _client.ConnectAsync(hostName, ""); // ConnectAsync() 并非连接的意思,udp 没有连接一说,这里用于设置发送数据的目标 lblMsg.Text += "准备往 127.0.0.1:2213 发送数据";
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString();
lblMsg.Text += Environment.NewLine;
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
} } // 实例化一个 DataWriter,用于发送数据
if (_writer == null)
_writer = new DataWriter(_client.OutputStream); try
{
string data = "hello webabcd " + DateTime.Now.ToString("hh:mm:ss");
_writer.WriteString(data); // 发送数据
await _writer.StoreAsync(); lblMsg.Text += "数据已发送: " + data;
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString();
lblMsg.Text += Environment.NewLine;
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} // 关闭客户端 socket 和服务端 socket
private void btnCloseSocket_Click(object sender, RoutedEventArgs e)
{
try
{
_writer.DetachStream(); // 分离 DataWriter 与 Stream 的关联
_writer.Dispose(); _client.Dispose();
_listener.Dispose(); lblMsg.Text += "服务端 socket 和客户端 socket 都关闭了";
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
}
}
}
OK
[源码下载]
重新想象 Windows 8 Store Apps (62) - 通信: Socket TCP, Socket UDP的更多相关文章
- 重新想象 Windows 8 Store Apps (60) - 通信: 获取网络信息, 序列化和反序列化
[源码下载] 重新想象 Windows 8 Store Apps (60) - 通信: 获取网络信息, 序列化和反序列化 作者:webabcd 介绍重新想象 Windows 8 Store Apps ...
- 重新想象 Windows 8 Store Apps (61) - 通信: http, oauth
[源码下载] 重新想象 Windows 8 Store Apps (61) - 通信: http, oauth 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通信 ...
- 重新想象 Windows 8 Store Apps (63) - 通信: WebSocket
[源码下载] 重新想象 Windows 8 Store Apps (63) - 通信: WebSocket 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通信 So ...
- 重新想象 Windows 8 Store Apps 系列文章索引
[源码下载][重新想象 Windows 8.1 Store Apps 系列文章] 重新想象 Windows 8 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...
- 重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传
[源码下载] 重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台任务 后台 ...
- 重新想象 Windows 8 Store Apps (68) - 后台任务: 控制通道(ControlChannel)
[源码下载] 重新想象 Windows 8 Store Apps (68) - 后台任务: 控制通道(ControlChannel) 作者:webabcd 介绍重新想象 Windows 8 Store ...
- 重新想象 Windows 8 Store Apps (34) - 通知: Toast Demo, Tile Demo, Badge Demo
[源码下载] 重新想象 Windows 8 Store Apps (34) - 通知: Toast Demo, Tile Demo, Badge Demo 作者:webabcd 介绍重新想象 Wind ...
- 重新想象 Windows 8 Store Apps (35) - 通知: Toast 详解
[源码下载] 重新想象 Windows 8 Store Apps (35) - 通知: Toast 详解 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通知 Toa ...
- 重新想象 Windows 8 Store Apps (36) - 通知: Tile 详解
[源码下载] 重新想象 Windows 8 Store Apps (36) - 通知: Tile 详解 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通知 Tile ...
随机推荐
- android实现自动升级并安装打开
http://blog.csdn.net/wa991830558/article/details/41014673 这是一个比较简单的程序,但网上还是有很多人问起这个问题,并且回答的人,也没有完全回答 ...
- VC++ 学习笔记(序):神一样的语言
总的来说,我觉得VC++是一门神一样的语言——它是公认最强大.最复杂的:它一切以效率为第一要务,却又不肯落伍,拼命兼容现在的新的语言设计特点.本来在别的语言很容与就避开的问题,在这里要用很高的技巧去设 ...
- ch5 MySQL 备份与恢复
第 5 章 MySQL 备份与恢复 前言 数据库的备份与恢复一直都是 DBA 工作中最为重要的部分之一,也是基本工作之一.任何正式环境的数据库都必须有完整的备份计划和恢复测试,本章内容将主要介绍 My ...
- [原]常用sqlserver数据库使用sql语句
1.表结构文档生成查询语句: SELECT 架构名 Then s.[name] Else '' End, 表名 Then D.name Else '' End, 表说明 Then isnull(F.v ...
- Embeding Python & Extending Python with FFPython
Introduction ffpython is a C++ lib, which is to simplify tasks that embed Python and extend Python. ...
- 微软MVC对架构的一点思考
毕业即将三年,在学校学习.做毕设一直使用拖控件的 Winform\WebForm,工作后公司采用MVC3架构做项目. 下面使用mvc的个人总结 : 1.架构上分层清晰.便于研发,耦合性好 2.缓存机制 ...
- DataGridView中添加CheckBox列用于选择行
DataGridView中添加CheckBox列用于选择行 1,编辑DataGridView,添加一列 CheckBox ,Name 赋值为 "select",如下图: 2,取消 ...
- Nginx upstream 长连接
原文: http://bollaxu.iteye.com/blog/900424 Nginx upstream目前只有短连接,通过HTTP/1.0向后端发起连接,并把请求的"Connecti ...
- Android客户端与PHP服务端交互(一)---框架概述
背景 作为一个普通上班族,总是想做一些自认为有意义的事情,于是乎准备成立一个工作室,尽管目前正在筹备阶段,但是之前有些朋友提出一些需求的时候,我发现自己的能力还是有限,直到最近和一些技术牛朋友聊起这事 ...
- Ubuntu进不入系统,一直停留在ubuntu图标画面(转)
Ubuntu进不入系统,一直停留在ubuntu图标画面(转) 在VMware中对Ubuntu进行“关闭电源”后,再次进入,一直停留在ubuntu的图标画面,无法进入系统了!网上也有别的网友碰到这个问题 ...