黑马程序员:Java基础总结
网络编程
ASP.Net+Android+IO开发
、
.Net培训
、期待与您交流!
网络编程
网络通讯要素
. IP地址
. 网络中设备的标识
. 不易记忆,可用主机名
. 本地回环地址:127.0.0.1 主机名:localhost
. 不易记忆,可用主机名
. 本地回环地址:127.0.0.1 主机名:localhost
. 端口号
. 用于标识进程的逻辑地址,不同进程的标识
. 有效端口:0~65535,其中0~1024系统使用或保留端口。
. 传输协议
. 通讯的规则
. 常见协议:TCP,UDP
. 常见协议:TCP,UDP
UDP
. 将数据及源和目的封装成数据包中,不需要建立连接
. 每个数据报的大小在限制在64k内
. 因无连接,是不可靠协议
. 不需要建立连接,速度快
. 将数据及源和目的封装成数据包中,不需要建立连接
. 每个数据报的大小在限制在64k内
. 因无连接,是不可靠协议
. 不需要建立连接,速度快
TCP
. 建立连接,形成传输数据的通道。
. 在连接中进行大数据量传输
. 通过三次握手完成连接,是可靠协议
. 必须建立连接,效率会稍低
Socket流机制
Socket就是为网络服务提供的一种机制。
通信的两端都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
java.net
类 InetAddress
InetAddress类在网络API套接字编程中扮演了一个重要角色。
该类没有构造方法
static InetAddress |
getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。 |
static InetAddress |
getLocalHost() 返回本地主机。 |
获得地址
String |
getHostAddress() 返回 IP 地址字符串(以文本表现形式)。 |
String |
getHostName() 获取此 IP 地址的主机名。 |
InetAddress myID = InetAddress .getLocalHost();
String a = myID.getHostAddress();
String b = myID.getHostName();
System.
out
.println(a);
out
.println(a);
System.
out
.println(b);
out
.println(b);
//获取网络中的主机域名和 ip地址
InetAddress myID = InetAddress . getByName(
"192.168.11.11"
);
"192.168.11.11"
);
System.
out
.println(myID.getHostName());
out
.println(myID.getHostName());
ServerSocket:服务器类
TCP通信(面向连接)
Socket:客户端类
网络编程类
DatagramSocket
此类表示用来发送和接收数据报包的套接字
此类表示用来发送和接收数据报包的套接字
UDP通信
(面向无连接)
(面向无连接)
DatagramPacket
此类表示数据报包
此类表示数据报包
UDP通信
DatagramSocket与DatagramPacket
建立发送端,接收端。
建立数据包。
调用Socket的发送接收方法。
关闭Socket。
建立发送端,接收端。
建立数据包。
调用Socket的发送接收方法。
关闭Socket。
发送端与接收端是两个独立的运行程序。
定义一个udp发送端。
在发送端,要在数据包对象中明确目的地
IP及端口。
IP及端口。
DatagramSocket(SocketAddress bindaddr) 创建数据报套接字,将其绑定到指定的本地套接字地址。 |
DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。 |
void |
send(DatagramPacket p) 从此套接字发送数据报包。 |
// 1,创建udp服务。通过DatagramSocket对象。
DatagramSocket ds =
new
DatagramSocket(8888);
new
DatagramSocket(8888);
// 2,确定数据,并封装成数据包。DatagramPacket(byte[] buf, int length, InetAddress
// address, int port)
byte
[] buf =
"udp ge men lai le "
.getBytes();
DatagramPacket dp =
new
DatagramPacket(buf, buf.
length
,
new
DatagramPacket(buf, buf.
length
,
InetAddress. getByName(
"192.168.1.254"
), 10000);
"192.168.1.254"
), 10000);
// 3,通过socket服务,将已有的数据包发送出去。通过send方法。
ds.send(dp);
// 4,关闭资源。
ds.close();
定义udp的接收端。
在接收端,要指定监听的端口。
在接收端,要指定监听的端口。
DatagramPacket(byte[] buf, int length) 构造 DatagramPacket ,用来接收长度为 length 的数据包。 |
void |
receive(DatagramPacket p) 从此套接字接收数据报包。 |
// 1,创建udp socket,建立端点。
DatagramSocket ds =
new
DatagramSocket(10000);
new
DatagramSocket(10000);
while
(
true
) {
// 2,定义数据包。用于存储数据。
byte
[] buf =
new
byte
[1024];
DatagramPacket dp =
new
DatagramPacket(buf, buf.
length
);
new
DatagramPacket(buf, buf.
length
);
// 3,通过服务的receive方法将收到数据存入数据包中。
ds.receive(dp);
// 阻塞式方法。
// 阻塞式方法。
// 4,通过数据包的方法获取其中的数据。
String ip = dp.getAddress().getHostAddress();
String data =
new
String(dp.getData(), 0, dp.getLength());
new
String(dp.getData(), 0, dp.getLength());
int
port = dp.getPort();
System.
out
.println(ip +
"::"
+ data +
"::"
+ port);
out
.println(ip +
"::"
+ data +
"::"
+ port);
}
// 5,关闭资源
// ds.close();
典型UDP服务:
一个聊天程序。
有收数据的部分,和发数据的部分。
这两部分需要同时执行。
那就需要用到多线程技术。
一个线程控制收,一个线程控制发。
因为收和发动作是不一致的,所以要定义两个run方法。
而且这两个方法要封装到不同的类中。
有收数据的部分,和发数据的部分。
这两部分需要同时执行。
那就需要用到多线程技术。
一个线程控制收,一个线程控制发。
因为收和发动作是不一致的,所以要定义两个run方法。
而且这两个方法要封装到不同的类中。
TCP通信
Socket和ServerSocket
建立客户端和服务器端
建立连接后,通过Socket中的IO流进行数
据的传输
关闭socket
建立客户端和服务器端
建立连接后,通过Socket中的IO流进行数
据的传输
关闭socket
客户端与服务器端是两个独立的应用程序
客户端
客户端需要明确服务器的ip地址以及端口,这样才 可以去试着建立连接,如果连接失败,会出现异 常。
连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已
经提供了输入流和输出流对象,通过 getInputStream(),getOutputStream()获取即可。
与服务端通讯结束后,关闭Socket。
客户端需要明确服务器的ip地址以及端口,这样才 可以去试着建立连接,如果连接失败,会出现异 常。
连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已
经提供了输入流和输出流对象,通过 getInputStream(),getOutputStream()获取即可。
与服务端通讯结束后,关闭Socket。
Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。 |
OutputStream |
getOutputStream() 返回此套接字的输出流。 |
// 创建客户端的socket服务。指定目的主机和端口
Socket s =
new
Socket(
"192.168.1.254"
, 10003);
new
Socket(
"192.168.1.254"
, 10003);
// 为了发送数据,应该获取socket流中的输出流。
OutputStream out = s.getOutputStream();
out.write(
"tcp ge men lai le "
.getBytes());
"tcp ge men lai le "
.getBytes());
s.close();
服务端:
服务端需要明确它要处理的数据是从哪个端口进入的。
当有客户端访问时,要明确是哪个客户端,
服务端需要明确它要处理的数据是从哪个端口进入的。
当有客户端访问时,要明确是哪个客户端,
可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。
当该客户端访问结束,关闭该客户端。
当该客户端访问结束,关闭该客户端。
ServerSocket(int port) 创建绑定到特定端口的服务器套接字。 |
Socket |
accept() 侦听并接受到此套接字的连接。 |
// 建立服务端socket服务。并监听一个端口。
ServerSocket ss =
new
ServerSocket(10003);
new
ServerSocket(10003);
// 通过accept方法获取连接过来的客户端对象。
while
(
true
) {
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.
out
.println(ip +
".....connected"
);
out
.println(ip +
".....connected"
);
// 获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。
InputStream in = s.getInputStream();
byte
[] buf =
new
byte
[1024];
int
len = in.read(buf);
System.
out
.println(
new
String(buf, 0, len));
out
.println(
new
String(buf, 0, len));
s.close();
// 关闭客户端.
// 关闭客户端.
}
// ss.close();
Tcp传输最容易出现的问题
客户端连接上服务端,两端都在等待,没有任何数据传输。
通过例程分析:
. 因为read方法或者readLine方法是阻塞式。
解决办法:
. 自定义结束标记
. 使用shutdownInput,shutdownOutput方法。
void |
shutdownInput() 此套接字的输入流置于“流的末尾”。 |
void |
shutdownOutput() 禁用此套接字的输出流。 |
ASP.Net+Android+IO开发
、
.Net培训
、期待与您交流!