- 网络编程
- 目录
- 1 网络编程概述
- 1.1计算机网络:
- 1.2网络编程的目的:
- 1.3网络编程中有两个主要的问题:
- 2通信要素1:IP和端口号
- IP 地址:InetAddress类的实例对象
- 端口号标识正在计算机上运行的进程(程序)
- 端口号与IP地址的组合得出一个网络套接字:Socket
- Socket分类:
- Socket类的常用构造器:
- Socket类的常用方法:
- 3通信要素2:网络协议
- 网络通信协议
- TCP协议:
- UDP协议:
- 4TCP网路编程
- 例1:客户端向服务端发送信息,服务端将数据显示在控制台上
- 客户端:
- 服务端:
- 例2客户端发送文件给服务端,服务端将文件保存在本地
- 客户端:
- 服务端:
- 客户端。并关闭相应的连接。
- 客户端:
- 服务端:
- 5UDP网络编程
- 流 程:
- 客户端:
- 服务端:
- 6URL编程
把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规
模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息、
共享硬件、软件、数据信息等资源。
直接或间接地通过网络协议与其它计算机实现数据交换,进行通讯。
1.3网络编程中有两个主要的问题:- 如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
- 找到主机后如何可靠高效地进行数据传输
-
唯一的标识 Internet 上的计算机(通信实体)
-
本地回环地址(hostAddress):127.0.0.1 主机名(hostName):localhost
-
IP地址分类方式1:IPV4 和 IPV6
- IPV4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。以点分进制表示,如192.168.0.1
- IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示,数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
-
IP地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用)。192.168.开头的就是私有址址,范围即为192.168.0.0–192.168.255.255,专门为组织机构内部使用
-
特点:不易记忆
-
InetAddress类没有提供公共的构造器,而是提供了如下几个静态方法来获取InetAddress实例
- public static InetAddress getLocalHost()
- public static InetAddress getByName(String host)
-
InetAddress提供了如下几个常用的方法
- public String getHostAddress():返回 IP 地址字符串(以文本表现形式)。
- public String getHostName():获取此 IP 地址的主机名
- public boolean isReachable(int timeout):测试是否可以达到该地址
- 不同的进程有不同的端口号
- 被规定为一个 16 位的整数 0~65535。
- 端口分类:
- 公认端口:0~1023。被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,Telnet占用端口23)
- 注册端口:1024~49151。分配给用户进程或应用程序。(如:Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等)。
- 动态/私有端口:49152~65535。
- 利用套接字(Socket)开发网络应用程序早已被广泛的采用,以至于成为事实上的标准。
- 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
- 通信的两端都要有Socket,是两台机器间通信的端点。
- 网络通信其实就是Socket间的通信。
- Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
- 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。
- 流套接字(stream socket):使用TCP提供可依赖的字节流服务
- 数据报套接字(datagram socket):使用UDP提供“尽力而为”的数据报服务
- public Socket(InetAddress address,int port)创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
- public Socket(String host,int port)创建一个流套接字并将其连接到指定主机上的指定端口号。
- public InputStream getInputStream()返回此套接字的输入流。可以用于接收网络消息
- public OutputStream getOutputStream()返回此套接字的输出流。可以用于发送网络消息
- public InetAddress getInetAddress()此套接字连接到的远程 IP 地址;如果套接字是未连接的,则返回 null。
- public InetAddress getLocalAddress()获取套接字绑定的本地地址。 即本端的IP地址
- public int getPort()此套接字连接到的远程端口号;如果尚未连接套接字,则返回 0。
- public int getLocalPort()返回此套接字绑定到的本地端口。 如果尚未绑定套接字,则返回 -1。即本端的端口号。
- public void close()关闭此套接字。套接字被关闭后,便不可在以后的网络连接中使用(即无法重新连接或重新绑定)。需要创建新的套接字对象。 关闭此套接字也将会关闭该套接字的InputStream 和OutputStream。
- public void shutdownInput()如果在套接字上调用 shutdownInput() 后从套接字输入流读取内容,则流将返回 EOF(文件结束符)。 即不能在从此套接字的输入流中接收任何数据。
- public void shutdownOutput()禁用此套接字的输出流。对于 TCP 套接字,任何以前写入的数据都将被发送,并且后跟 TCP 的正常连接终止序列。 如果在套接字上调用 shutdownOutput() 后写入套接字输出流,则该流将抛出 IOException。 即不能通过此套接字的输出流发送任何数据。
-
计算机网络中实现通信必须有一些约定,即通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。
-
计算机网络通信涉及内容很多,比如指定源地址和目标地址,加密解密,压缩解压缩,差错控制,流量控制,路由控制,如何实现如此复杂的网络协议呢?
-
在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常用的复合方式是层次方式,即同层间可以通信、上一层可以调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展。
-
IP(Internet Protocol)协议是网络层的主要协议,支持网间互连的数据通信。
-
TCP/IP协议模型从更实用的角度出发,形成了高效的四层体系结构,即物理链路层、IP层、传输层和应用层。
- 使用TCP协议前,须先建立TCP连接,形成传输数据通道
- 传输前,采用“三次握手”方式,点对点通信,是可靠的
- TCP协议进行通信的两个应用进程:客户端、服务端。
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低(相对UDP)
- 生活例子:打电话
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据报的大小限制在64K内
- 发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
- 可以广播发送
- 发送数据结束时无需释放资源,开销小,速度快
- 生活例子:视频直播
package com.tongda.test;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
try {
// 第一步:创建socket对象,指明服务器的IP和端口号
InetAddress address = InetAddress.getByName("127.0.0.1");
socket = new Socket(address, 8888);
// 第二步:获取输出流,用于输出数据
os = socket.getOutputStream();
// 第三步:写出数据
os.write("我是客户端 你好,我是雷神".getBytes());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 第四步:关闭资源
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务端:
package com.tongda.test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
ServerSocket ss = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream aos = null;
try {
// 1 创建服务器端的ServerSocket,指明自己的端口号
ss = new ServerSocket(8888);
// 2 调用accept()表示接受来自客户端的socket
socket = ss.accept();
// 3 获取输入流,
is=socket.getInputStream();
//4 从输入流读取数据
aos = new ByteArrayOutputStream();
byte []buffer=new byte[20];
int len;
while((len=is.read(buffer))!=-1) {
aos .write(buffer,0,len);
}
System.out.println(aos);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (aos !=null) {
try {
aos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is!=null) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (socket!=null ) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (ss !=null) {
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
例2客户端发送文件给服务端,服务端将文件保存在本地
客户端:
package com.tongda.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
//客户端发送文件给服务端,服务端将文件保存在本地
public class Client {
public static void main(String[] args) {
Socket socket=null;
OutputStream os=null;
FileInputStream fis=null;
try {
// 第一步:创建socket对象,指明服务器的IP和端口号
socket=new Socket(InetAddress.getByName("127.0.0.1"),8989);
//获取输出流
os=socket.getOutputStream();
fis=new FileInputStream(new File("072-2.jpg"));
//写出数据
byte []buff=new byte[1024];
int len;
while ((len=fis.read(buff))!=-1) {
//写出数据
os.write(buff,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fis!=null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os!=null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务端:
package com.tongda.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
//接受客户端发送过来的数据
ServerSocket ss=null;
InputStream is=null;
Socket socket=null;
FileOutputStream fos=null;
try {
//1 创建服务器端的ServerSocket,指明自己的端口号
ss=new ServerSocket(8989);
//接收
socket=ss.accept();
is=socket.getInputStream();
fos=new FileOutputStream(new File("072-3.jpg"));
byte[] buff=new byte[1024];
int len ;
while((len=is.read(buff))!=-1) {
fos.write(buff,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (socket!=null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is!=null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ss!=null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
例三:.从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给
客户端。并关闭相应的连接。 客户端:package com.tongda.test ;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
FileInputStream fis = null;
ByteArrayOutputStream baos = null;
try {
socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
fis = new FileInputStream(new File("072-2.jpg"));
os = socket.getOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
// 关闭数据的输出
socket.shutdownOutput();
// 5.接收来自于服务器端的数据,并显示到控制台上
InputStream is = socket.getInputStream();
baos = new ByteArrayOutputStream();
byte[] bufferr = new byte[20];
int len1;
while ((len1 = is.read(buffer)) != -1) {
baos.write(buffer, 0, len1);
}
System.out.println(baos.toString());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务端:
package com.tongda.test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
ServerSocket ss = null;
Socket socket = null;
InputStream is = null;
FileOutputStream fos = null;
// 6.服务器端给予客户端反馈
OutputStream os = null;
try {
ss = new ServerSocket(9090);
socket = ss.accept();
is = socket.getInputStream();
fos = new FileOutputStream(new File("072-3.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
//System.out.println("图片传输完成");
os = socket.getOutputStream();
os.write("你好,照片我已收到,非常漂亮!".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5UDP网络编程
流 程:
- DatagramSocket与DatagramPacket
- 建立发送端,接收端
- 建立数据包
- 调用Socket的发送、接收方法
- 关闭Socket
package com.tongda.test;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Client {
public static void main(String[] args) {
DatagramSocket ds = null;
try {
ds = new DatagramSocket();
byte[] by = "hello".getBytes();
DatagramPacket dp = new DatagramPacket(by, 0, by.length, InetAddress.getByName("127.0.0.1"), 8989);
ds.send(dp);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ds != null)
ds.close();
}
}
}
服务端:
package com.tongda.test;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Server {
public static void main(String[] args) {
DatagramSocket ds = null;
try {
ds = new DatagramSocket(8989);
byte[] by = new byte[1024];
DatagramPacket dp = new DatagramPacket(by, by.length);
ds.receive(dp);
String str = new String(dp.getData(), 0, dp.getLength());
System.out.println(str + "--" + dp.getAddress());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ds != null)
ds.close();
}
}
}
6URL编程
-
URL(Uniform Resource Locator):统一资源定位符,它表示 Internet 上某一资源的地址。
-
URL的基本结构由5部分组成:
- <传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表
package com.tongda.test;
import java.net.MalformedURLException;
import java.net.URL;
public class URLTest {
public static void main(String[] args) {
try {
URL url = new URL("http://localhost:8080/examples/beauty.jpg?username=Tom");
// public String getProtocol( ) 获取该URL的协议名
System.out.println(url.getProtocol());
// public String getHost( ) 获取该URL的主机名
System.out.println(url.getHost());
// public String getPort( ) 获取该URL的端口号
System.out.println(url.getPort());
// public String getPath( ) 获取该URL的文件路径
System.out.println(url.getPath());
// public String getFile( ) 获取该URL的文件名
System.out.println(url.getFile());
// public String getQuery( ) 获取该URL的查询名
System.out.println(url.getQuery());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}



