网络编程
网络模型
OSI参考模型(应用层,表示层,会话层,传输层,网络层,数据链路层,物理层)
TCP/IP参考模型(应用层,传输层,网际层,主机至网络层)
TCP:Transmission Control Protocol 传输控制协议
IP:Internet Protocol 互联网协议
网络通讯要素
IP地址:网络中设备的标识
端口号:用于标识进程的逻辑地址,不同进程的标识
有效端口:0~65535,其中0~1024系统使用或保留端口
传输协议:通信规则。
应用层的协议有:HTTP 超文本传输协议 HyperText Transfer Protocol
FTP 文件传输协议 File Transfer Protocol
SMTP 简单邮件传输协议
Telnet 远程登录服务
http://127.0.0.1
http://localhost
127和localhost的映射关系就在本机上。
c:\windows\systems32\drivers\ext\hosts
127.0.0.1,本地回环地址,本机未配置任何IP地址的情况下的地址。
可用于测试本机网卡好坏。DOS——>ping 127.0.0.1
TCP/IP模型中,java网络编程在传输层和网际层,java Web开发在应用层。
每个层都有自己的传输协议。传输层常见的协议有TCP和UDP,网际层最常见的就是IP,
应用层的是HTTP和FTP。
java.net——>InetAddress(用于描述IP的对象)
UDP
特点:面向无连接,数据包有限制,速度快
将数据源和目的封装在数据包中,不需要建立连接。每个数据包的大小限制
在64K内,可以分多包发。因无连接,是不可靠协议,但速度快。
UDP传输只需数据源端在即可,接收源端断开没关系。接收端断开时数据包会直
接丢失。
例:凌波教学用软件,网络视频会议,桌面共享
TCP
特点:面向连接.必须先启动服务端再启动客户端。
建立连接,形成传输数据的通道。在连接中进行大数据量的传输。
通过三次握手完成连接,是可靠的。必须建立连接,效率稍低。
单方面断开数据会停止传输。
通过三次握手可以判断对方是否在线:会建立通路,A首先发送一次数据,B收到后发
网络模型
OSI参考模型(应用层,表示层,会话层,传输层,网络层,数据链路层,物理层)
TCP/IP参考模型(应用层,传输层,网际层,主机至网络层)
TCP:Transmission Control Protocol 传输控制协议
IP:Internet Protocol 互联网协议
网络通讯要素
IP地址:网络中设备的标识
端口号:用于标识进程的逻辑地址,不同进程的标识
有效端口:0~65535,其中0~1024系统使用或保留端口
传输协议:通信规则。
应用层的协议有:HTTP 超文本传输协议 HyperText Transfer Protocol
FTP 文件传输协议 File Transfer Protocol
SMTP 简单邮件传输协议
Telnet 远程登录服务
http://127.0.0.1
http://localhost
127和localhost的映射关系就在本机上。
c:\windows\systems32\drivers\ext\hosts
127.0.0.1,本地回环地址,本机未配置任何IP地址的情况下的地址。
可用于测试本机网卡好坏。DOS——>ping 127.0.0.1
TCP/IP模型中,java网络编程在传输层和网际层,java Web开发在应用层。
每个层都有自己的传输协议。传输层常见的协议有TCP和UDP,网际层最常见的就是IP,
应用层的是HTTP和FTP。
java.net——>InetAddress(用于描述IP的对象)
UDP
特点:面向无连接,数据包有限制,速度快
将数据源和目的封装在数据包中,不需要建立连接。每个数据包的大小限制
在64K内,可以分多包发。因无连接,是不可靠协议,但速度快。
UDP传输只需数据源端在即可,接收源端断开没关系。接收端断开时数据包会直
接丢失。
例:凌波教学用软件,网络视频会议,桌面共享
TCP
特点:面向连接.必须先启动服务端再启动客户端。
建立连接,形成传输数据的通道。在连接中进行大数据量的传输。
通过三次握手完成连接,是可靠的。必须建立连接,效率稍低。
单方面断开数据会停止传输。
通过三次握手可以判断对方是否在线:会建立通路,A首先发送一次数据,B收到后发
送返回数据,A再发送数据确认。如:A:在? B:我在。 A:恩,知道你在了。
import java.net.*;
class IPDemo
{
public static void main(String[] args) throws Exception
{
//method_1();//打印本机名和地址
method_2();//打印指定机器的名和地址
}
public static void method_1() throws Exception
{
InetAddress i = InetAddress.getLocalHost();//打印本机名和地址
sop(i.toString());
sop("Address:"+i.getHostAddress());
sop("Name:"+i.getHostName());
}
public static void method_2() throws Exception
{
InetAddress i = InetAddress.getByName("192.168.1.254");
sop("Address:"+i.getHostAddress());
sop("Name:"+i.getHostName());
/*
打印地址之后打印名字很慢,若IP地址和对应的主机名这个映射关系不在网络上,
不能够解析成功。打印的名字仍是IP地址。
*/
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
网络编程其实就是Socket编程。
Socket(插座)就是为网络服务提供的一种机制,通信的两端都有Socket,网络通信其实就是
Socket间的通信,数据在两个Socket间通过IO传输。
类似于两台机器用网线连接,有接口。不同主机上的相同软件之间的连接一样,即Socket。
java.net——>DatagramSocket 此类表示用来发送和接收数据报包的套接字(Socket)。
import java.net.*;
/*
需求:通过UDP传输方式,将一段文字数据发送出去。
定义一个UDP发送端
思路:
1.建立UDPsocket服务。即建立端点
2.提供数据,并将数据封装到数据包中。
3.通过socket服务的发送功能将数据包发送出去。
4.关闭资源。
*/
class UDPSend
{
public static void main(String[] args) throws Exception
{
//创建udp服务,通过DatagramSocket对象。
DatagramSocket ds = new DatagramSocket(7891);
//确定数据并封装成数据包
//DatagramPacket(byte[] buf,int length,InetAddress address,int port);
byte[] buf = "udp data is coming".getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,
InetAddress.getByName("127.0.0.1"),10000);
//通过socket服务,用send方法将已有的数据包发送出去
ds.send(dp);
//关闭资源
ds.close();
}
}
//UDPSend 此代码发送的数据将会丢失,因为面向无连接。
/*
定义UDP的接收端,通常会在定义udpsocket服务时监听一个端口,其实就是给
这个接受网络应用程序定义一个数字标识,方便明确哪些数据过来该应用程序
可以处理。若不定义,系统会给其随机分配一个而造成发送端发送时的端口与
接收端的不匹配而使数据丢失。
需求:定义一个应用程序,用于接收udp协议传输的数据并处理。
思路:
1.定义UDPsocket服务。
2.定义一个数据包,因为要存储接收到的字节数据。
因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
3.通过socket服务的receive方法将受到的数据存入已定义好的数据包中。
4.通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上。
5.关闭资源
接收端开启后需要接收后才停止,因其有一个阻塞式方法:ds.receive(dp);
*/
class UDPReceive
{
public static void main(String[] args) throws Exception
{
//创建UDPsocket服务,建立端点
DatagramSocket ds = new DatagramSocket(10000);//指定10000端口
/*此句不能放在循环中,下面的语句可以放。
因此句若放循环会使多个服务用到同一端口而发生BindException异常。
*/
/*
//定义数据包,用于存储数据
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//通过服务的receive方法将收到的数据存入数据包中
ds.receive(dp);
//通过数据包的方法获取其中的数据,包含地址、端口和数据
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
int port = dp.getPort();
//System.out.println(buf.length);
System.out.println(ip+"::"+data+"::"+port);
//port 发送端的数字标识,是系统自动分配的。也可以在发送端指定。
//关闭资源
ds.close(); */
while(true)
{
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
int port = dp.getPort();
System.out.println(ip+"::"+data+"::"+port);
//ds.close();
}
}
}
//需要运行两个控制台。还要先运行接收端再开发送端。
192.168.1.0 :代表一个网络地址段。
192.168.1.255 :代表这个段里面的广播地址。
import java.net.*;
import java.io.*;
class UdpSend2
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds = new DatagramSocket();
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
byte[] buf = line.getBytes();
/*DatagramPacket dp = new DatagramPacket(buf,buf.length,
InetAddress.getByName("127.0.0.1"),10001);*/
DatagramPacket dp = new DatagramPacket(buf,buf.length,
InetAddress.getByName("127.0.0.1"),10001);
//此包用于将长度为length的包发送到指定主机的指定端口号
ds.send(dp);
}
ds.close();
}
}
class UdpReceive2
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds = new DatagramSocket(10001);
while(true)
{
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//此包用于接受长度为length的数据包
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
System.out.println(ip+"::"+data);
}
}
}
//聊天程序
import java.net.*;
import java.io.*;
/*
编写一个聊天程序,分为收数据和发数据。
这两部分需要同时执行,需要用到多线程技术。
一个线程控制收,另一个控制发。
因为收和发动作是不一致的,所以要定义两个run方法。
而且这两个方法要封装到不同的类中。
*/
class Send implements Runnable
{
private DatagramSocket ds;
public Send(DatagramSocket ds)
{
this.ds = ds;
}
public void run()//覆盖run方法
{
try
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10002);
ds.send(dp);
}
}
catch (Exception e)
{
throw new RuntimeException("发送端发送失败!");
}
}
}
class Rece implements Runnable
{
private DatagramSocket ds;
public Rece(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
while(true)
{
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
//byte[] getData();返回数据缓冲区。
//getLength();返回将要接收到的数据的长度。
System.out.println(ip+"::"+data);
}
}
catch (Exception e)
{
throw new RuntimeException("接收端接收失败!");
}
}
}
class ChatDemo
{
public static void main(String[] args) throws Exception
{
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = new DatagramSocket(10002);
//发送端端口可由系统分配,但接收端端口需要指定。
//一定要创建Send和Rece这两个类的对象。
//因要把Runnable接口的子类对象传给Thread的构造函数。
new Thread(new Send(sendSocket)).start();
new Thread(new Rece(receSocket)).start();
}
}
TCP传输
Socket和ServerSocket
建立客户端和服务端
建立连接后,通过Socket中的IO流进行数据的传输。
关闭Socket。
客户端和服务端应该是两个独立的应用程序。
import java.net.*;
import java.io.*;
/*
Tcp传输。
1.TCP分客户端和服务端。
2.客户端对应的对象是Socket。
服务端对应的对象是ServerSocket。
*/
/*
客户端
在Socket对象建立时就可以去连接指定主机。
因为Tcp是面向连接的,所以在建立Socket服务时,
就要有服务端存在并连接成功。形成通路后,在该通道进行数据的传输。
需求:给服务端发送一个文本数据。
步骤:
1.创建Socket服务,并制定要连接的主机和端口
*/
class TcpClient//客户端
{
public static void main(String[] args) throws Exception
{
//创建客户端的Socket服务,指定目的的主机和端口
Socket s = new Socket("127.0.0.1",10003);
//若此步成功,即通路建立了。通路一建立就会有Socket流(即网络流)。
//此Socket流中有方法可以拿到输入流或输出流,不需要New。
//为了发送数据需要获取Socket流中的输出流
//因为数据可能是任何类型,所以用字节流
OutputStream out = s.getOutputStream();
out.write("Tcp is Coming".getBytes());
s.close();//Socket关闭,流也会被关闭
}
}
/*
服务端会跟多个客户端进行连接,之所以不会把数据发到不匹配的客户端,
原因是服务端跟SocketA连接后是使用SocketA的流跟其交流,所以不会发错。
Socket用其out向服务端发送,服务端使用A的in接收后用A的out向A发送,A用in接收。
需求:定义端点接收数据并打印在控制台上。
服务端:
1.建立服务端的Socket服务,ServerSocket();
并监听一个端口,即打数字标识。
2.获取连接过来的客户端对象,
通过ServerSocket的accept方法。此方法是阻塞式的,因没有连接就会等。
3.客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到
该客户端对象的读取流来读取发过来的数据,并打印在控制台上。
4.关闭服务端。(可选,因还有其他客户端)
*/
class TcpServer
{
public static void main(String[] args) throws Exception
{
//建立服务端Socket服务,并监听一个端口。
ServerSocket ss = new ServerSocket(10003);
//通过accept方法获取连接过来的客户端对象。
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.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));
s.close();//关闭客户端
}
}
import java.io.*;
import java.net.*;
/*
演示TCP的传输的客户端和服务端的互访。
需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息。
*/
/*
客户端:
1.建立Socket服务,指定要连接的主机和端口。
2.获取Socket流中的输出流,将数据写到该流中,通过网络发送给服务端。
3.获取Socket流中的输入流,将服务端反馈的数据获取到并打印。
4.关闭客户端资源。
*/
class TcpClient2
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket("127.0.0.1",10004);
OutputStream out = s.getOutputStream();
out.write("服务端,你好。".getBytes());
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String(buf,0,len));
s.close();
}
}
class TcpServer2
{
public static void main(String[] args) throws Exception
{
ServerSocket ss = new ServerSocket(10004);
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.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));
OutputStream out = s.getOutputStream();
out.write("收到,你也好。".getBytes());
s.close();
ss.close();
}
}
import java.io.*;
import java.net.*;
/*
需求:建立一个文本转换服务器。
客户端给服务器端发送文本,服务端会将文本转换为大写再返回给客户端。
而且客户端可以不断的进行文本转换,当客户端输入over时转换结束。
分析:
客户端:
既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考。
源:键盘录入
目的:网络设备,网络输出流
而且操作的是文本数据,可以选择字符流。
步骤:
1.建立服务
2.获取键盘录入
3.将数据发给服务端
4.获取服务端返回的大写数据
5.结束,关闭资源。
都是文本数据,可以使用字符流进行操作,同时提高效率可以加入缓冲区。
*/
class TransClient
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket("127.0.0.1",10005);
//定义读取键盘数据的流对象。
BufferedReader bufr = new BufferedReader
(new InputStreamReader(System.in));
//定义目的,将数据写入到Socket输出流,发给服务端。
BufferedWriter bufOut = new BufferedWriter
(new OutputStreamWriter(s.getOutputStream()));
//代替上句:
//PrintWriter out = new PrintWriter(s.getOutputStream,true);
//定义一个Socket读取流,读取服务器端返回的大写信息。
BufferedReader bufIn = new BufferedReader
(new InputStreamReader(s.getInputStream()));
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
/*
输入over,客户端结束,服务端未判断但也结束了。
因客户端的s.close();结束时会返回-1,服务端接
收到-1后便会结束。
*/
bufOut.write(line);
//发送的数据没有回车符,而服务端在读一行数据
//时判断的是回车标记,所以需要加回车符
bufOut.newLine();
bufOut.flush();
//代替上三句:(对应PrintWriter)
//out.println(line);
String str = bufIn.readLine();
System.out.println("server:"+str);
}
bufr.close();
s.close();
}
}
/*
服务端:
源:Socket读取流。
目的:Socket输出流。
都是文本,装饰。
*/
class TransServer
{
public static void main(String[] args) throws Exception
{
ServerSocket ss = new ServerSocket(10005);
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"...connected");
//读取Socket读取流中的数据
BufferedReader bufIn = new BufferedReader(
new InputStreamReader(s.getInputStream()));
//目的,Socket输出流。将大写数据写入到Socket输
//出流,并发送给客户端。
BufferedWriter bufOut = new BufferedWriter(
new OutputStreamWriter(s.getOutputStream()));
//PrintWriter out = new PrintWriter(s.getOutputStream(),true);
String line = null;
while((line=bufIn.readLine())!=null)
{
System.out.print(line);
bufOut.write(line.toUpperCase());
//客户端同样是用的readLine();所以也需要结束标记和刷新
bufOut.newLine();
bufOut.flush();
//out.println(line.toUpperCase());
}
s.close();
ss.close();
}
}
/*
该例子出现的问题。
现象:客户端和服务端都在莫名的等待。
原因:客户端和服务端都有阻塞式的方法,这些方法没有读到结束标记,那么
就会一直等待而导致两端都等待。
*/
ip IP Internet protocol
icmp ICMP Internet control message protocol
ggp GGP Gateway-gateway protocol
tcp TCP Transmission control protocol
egp EGP Exterior gateway protocol
pup PUP PARC universal packet protocol
udp UDP User datagram protocol
hmp HMP Host monitoring protocol
xns-idp XNS-IDP Xerox NS IDP
rdp RDP "reliable datagram" protocol
ipv6 IPv6 Internet protocol IPv6
ipv6-route IPv6-Route Routing header for IPv6
ipv6-frag IPv6-Frag Fragment header for IPv6
esp ESP Encapsulating security payload
ah AH Authentication header
ipv6-icmp IPv6-ICMP ICMP for IPv6
ipv6-nonxt IPv6-NoNxt No next header for IPv6
ipv6-opts IPv6-Opts Destination options for IPv6
rvd RVD MIT remote virtual disk