一、网络编程入门


1、网络编程概述

  • 计算机网络
    是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统
  • 网络编程
    在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换

2、网络编程三要素

2.1、IP地址

IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址。 IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异

IP地址:是网络中设备的唯一标识

  • IP地址分为两大类

    • IPv4:是给每个连接在网络上的主机分配一个32bit地址。按照TCP/IP规定,IP地址用二进制来表示,每个IP地址长32bit,也就是4个字节。例如一个采用二进制形式的IP地址是“11000000 10101000 00000001 01000010”,这么长的地址,处理起来也太费劲了。为了方便使用,IP地址经常被写成十进制的形式,中间使用符号“.”分隔不同的字节。于是,上面的IP地址可以表示为“192.168.1.66”。IP地址的这种表示法叫做“点分十进制表示法”,这显然比1和0容易记忆得多

    • IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。为了扩大地址空间,通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,这样就解决了网络地址资源数量不够的问题

  • DOS常用命令:

    • ipconfig:查看本机IP地址
    • ping IP地址:检查网络是否连通
  • 特殊IP地址:

    • 127.0.0.1:是回送地址,可以代表本机地址,一般用来测试使用

2.2、端口号

端口号(port number) 所谓端口,就好像门牌号一样,客户端可以通过IP地址找到对应的服务器端,但是服务器端是有很对端口的,每个应用程序对应一个端口号,通过类似门牌号的端口号,客户端才能真正的访问到服务器。为了对端口号进行区分,将每个端口进行了编号,这就是端口号。

TCP与UDP段结构中端口地址都是16比特,可以有在0—-65535范围内的端口号。对于这65536个端口号有以下的使用规定 :
(1)端口号小于256的定义为常用端口,服务器一般都是通过常用端口号来识别的。任何TCP/IP实现所提供的服务都用1—-1023之间的端口号,是由ICANN来管理的;端口号从1024—-49151是被注册的端口,也成为“用户端口”,被IANA指定为特殊服务使用;
(2)客户端只需保证该端口号在本机上是唯一的就可以了。客户端端口号因存在时间很短暂又称临时端口号;
(3)大多数TCP/IP实现给临时端口号分配1024—-5000之间的端口号。大于5000的端口号是为其他服务器预留的

2.3、通信协议

网络通信协议就是一种网络通信的语言,为连接不同操作系统和不同硬件体系结构的互联网络提供通信支持,是一种网络通用的语言

UDP协议


  • 用户数据报协议(User Datagram Protocol)
  • UDP是无连接通信协议:即在数据传输时,数据的发送端和接受端不建立逻辑链接。
  • 简单来说,当一计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在接收数据时,也不会向发送端反馈是否收到数据。
  • 由于使用UDP协议消耗的资源小,通信效率高,所以通常会用于音频,视频和普通数据的传输

TCP协议


  • 传输控制协议(Transmission Control Portocol)
  • TCP协议是面向链接的通信协议,即传输数据之前,在发送端和接收端之间建立逻辑链接,然后再传输数据它提供了两台计算机之间可靠无差错的数据传输。
  • 在TCP链接中必须要明确客户端和服务端,由客户端向服务端发出链接请求,每次链接的创建都需要经过“三次握手”
    • 三次握手:TCP协议中,在发送数据的准备阶段,客户端于服务端之间的三次交互,以保证链接的可靠
      • 第一次握手:客户端向服务端发出链接请求,等待服务器确认
      • 第二次握手:服务端向客户端回送一个相应,通知客户收到了链接请求
      • 第三次握手:客户端再次向服务器端发送确认信息,确认链接

src=http___pic3.zhimg.com_v2-b32ce00dca8c40f83212f6a256e04e6e_b.jpg&refer=http___pic3.zhimg.jpg

3、InetAddress 【应用】

InetAddress类用来封装我们前面讨论的数字式的IP地址和该地址的域名。   你通过一个IP主机名与这个类发生作用,IP主机名比它的IP地址用起来更简便更容易理解。   InetAddress类内部隐藏了地址数字。

InetAddress类没有明显的构造函数。为生成一个InetAddress对象,必须运用一个可用的工厂方法。
工厂方法(factory method)仅是一个类中静态方法返回一个该类实例的约定。

3.1、InetAddress对象的获取

InetAddress的构造函数不是公开的(public),所以需要通过它提供的静态方法来获取,有以下的方法:

方法 说明
static InetAddress[] getAllByName(String host)
static InetAddress getByAddress(byte[] addr)

| | | static InetAddress getByAddress(String host,byte[] addr) | | | static InetAddress getByName(String host) | 常用方法 getByName,通过主机名获得InetAddress对象,可以是IP地址
getLocalHost,获得本机的InetAddress对象 | | static InetAddress getLocalHost() | |

3.3 InetAddress的方法

返回值 方法 说明
String getCanonicalHostName() 获取此IP地址的完全限定域名。
String getHostAddress() 返回文本显示中的IP地址字符串。
String getHostName() 获取此IP地址的主机名。
int hashCode() 返回此IP地址的哈希码。
boolean isAnyLocalAddress() 检查通配符地址中的InetAddress的实用程序。
boolean isLinkLocalAddress() 检查InetAddress是否是链接本地地址的实用程序。
boolean isLoopbackAddress() 检查InetAddress是否是一个环回地址的实用程序。
boolean isMCGlobal() 检查多播地址是否具有全局范围的实用程序。
boolean isMCLinkLocal() 检查组播地址是否具有链路范围的实用程序。
boolean isMCNodeLocal() 检查多播地址是否具有节点范围的实用程序。
boolean isMCOrgLocal() 检查组播地址是否具有组织范围的实用程序。
boolean isMCSiteLocal() 检查多播地址是否具有站点范围的实用程序。
boolean isMulticastAddress() 检查InetAddress是否是IP组播地址的实用程序。
boolean isReachable(int timeout) 测试该地址是否可达。
boolean isReachable(NetworkInterface netif, int ttl, int timeout) 测试该地址是否可达。
boolean isSiteLocalAddress() 检查InetAddress是否是站点本地地址的实用程序。
String toString() 将此IP地址转换为 String 。

二、UDP通信程序


1、UDP发送数据

Java中的UDP通信

  1. UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是两个Socket只是发送,接受数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念
  2. Java提供了DatagrameSocket类作为基于UDP协议的Socket
  • 构造方法 | 方法名 | 说明 | | —- | —- | | DatagramSocket() | 创建数据报套接字,并将其绑定到本机地址上的任意可用端口 | | DatagramPacket(byte[] buf,int len,lentAddress add,int port) | 创建数据包,发送长度为len的数据包到指定主机的指定端口 | | DatagramSocket(int port) | 创建数据报套接字,并将其绑定到本机地址指定端口上 |
  • 实例方法 | 方法名 | 说明 | | —- | —- | | void send(DatagramPacket p) | 发送数据包 | | void close() | 关闭数据报套接字 | | void receive(DatagramPacket p) | 从此套接字接受数据包 |
  • 发送数据的步骤
    • 创建发送端的Socket对象—(DatagramSocket)
    • 创建数据包,并把数据打包
    • 调用DatagramSocket对象的方法发送数据
    • 关闭发送端
  • 代码演示 ```java import java.io.IOException; import java.net.*;

public class DatagramSocket_sent { public static void main(String[] args) throws IOException {

  1. //创建发送端的DatagramSocket对象
  2. DatagramSocket ds = new DatagramSocket();
  3. //构建一个数据包
  4. byte[] bytes = "这是一个由UDP协议发出的字符串".getBytes();
  5. DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"),9999);
  6. //由DatagramSocket对象发送数据包dp
  7. ds.send(dp);
  8. //关闭套接字
  9. ds.close();

} }

  1. <a name="9xGzm"></a>
  2. ## 2、UDP接受数据
  3. - 接收数据的步骤
  4. - 创建接收端的Socket对象(DatagramSocket)
  5. - 创建一个数据包,用于接收数据
  6. - 调用DatagramSocket对象的方法接收数据
  7. - 解析数据包,并把数据在控制台显示
  8. - 关闭接收端
  9. - 数据包构造方法
  10. | 方法名 | 说明 |
  11. | --- | --- |
  12. | DatagramPacket(byte[] buf, int len) | 创建一个DatagramPacket用于接收长度为len的数据包 |
  13. - 相关方法
  14. | 方法名 | 说明 |
  15. | --- | --- |
  16. | byte[] getData() | 返回数据缓冲区 |
  17. | int getLength() | 返回要发送的数据的长度或接收的数据的长度 |
  18. - 示例代码
  19. ```java
  20. import java.io.IOException;
  21. import java.net.DatagramPacket;
  22. import java.net.DatagramSocket;
  23. public class DatagramSocket_receive {
  24. public static void main(String[] args) throws IOException {
  25. //new DatagramSocket套接字并指定端口来接收数据
  26. DatagramSocket ds = new DatagramSocket(9999);
  27. //new DatagramPacket 数据包来接受存放数据
  28. byte[] bytes = new byte[1024];
  29. DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
  30. //接收数据
  31. ds.receive(dp);
  32. //获取数据包中字节数组中接收到的数据
  33. byte[] data = dp.getData();
  34. //将存放字符的字节数组转换成字符串
  35. String s = new String(data, 0, dp.getLength());
  36. //输出接收的字符串
  37. System.out.println("接收的数据为:"+s);
  38. //关闭接收端
  39. ds.close();
  40. }
  41. }

三、TCP通信程序


1、TCP发送数据—>客户端

  • Java中的TCP通信

    • Java对基于TCP协议的网络通信提供了良好的封装,使用Socket对象来戴白哦两端的通信端口,并通过Socket产生的IO流来进行网络通信。
    • Java为客户端提供了Socket类,为服务端提供了ServerSocket类
  • 构造方法 | 方法名 | 说明 | | —- | —- | | Socket(InetAddress address,int port) | 创建流套接字并将其连接到指定主机指定端口 | | Socket(String host,int port) | 创建流套接字并将其连接到指定IP指定端口 |

  • 相关方法 | 方法名 | 说明 | | —- | —- | | InputStream getInputStream() | 返回此套接字的输入流 | | OutPutStream getOutPutStream() | 返回此套接字的输出流 | | void close() | 关闭socket释放资源 |
  • 客户端实现步骤

    1. 创建Socket对象
    2. 通过Socket对象获得出入输出流
    3. 输入流:服务器—->本机
    4. 输出流:本机—->服务器
    5. 操作完成关闭输入输出流和socket对象释放资源
  • 代码示例(给服务器端发送信息,并在控制台输出服务器端返回的数据)
  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.net.Socket;
  5. import java.nio.charset.StandardCharsets;
  6. public class ClientDemo {
  7. public static void main(String[] args) throws IOException {
  8. //new 客户端 Socket对象 并指定连接到的主机和端口
  9. Socket socket = new Socket("localhost",9999);
  10. //获得Socket的输出流对象 发送数据 本机-->服务端
  11. OutputStream os = socket.getOutputStream();
  12. os.write("通过TCP协议发送的数据".getBytes(StandardCharsets.UTF_8));
  13. //获得Socket的输入流对象 接收数据 服务端-->本机
  14. InputStream is = socket.getInputStream();
  15. byte[] bytes = new byte[1024];
  16. int len = is.read(bytes);
  17. String data = new String(bytes, 0, len);
  18. System.out.println("服务器返回数据:"+data);
  19. //释放资源
  20. is.close();
  21. os.close();
  22. socket.close();
  23. }
  24. }

2、TCP接收数据—>服务端

  • TCP协议的连接只能由客户端主动发起,服务端需要监听指定端口,等待连接。

  • ServerSocket对象的accept()方法可以监听指定端口,并在客户端请求是返回Socket对象

  • 通过ServerSocket返回的Socket对象获取输入输出流和客户端之间交换数据

  • 构造方法(ServerSocket)
方法名 说明
ServerSocket(int port) 创建绑定到指定端口的苏武器套接字
  • 相关方法(ServerSocket)
方法名 说明
Socket accept( ) 监听要连接到此Socket并接收它返回链接的Socket对象
  • 服务器端实现步骤

    1. 创建服务器套接字ServerSocket对象,并指定端口
    2. 调用ServerSocket对象的accept方法监听要连接到此的客户端,并返回连接的Socket对象
    3. 通过建立连接后获得的Socket对象获得连接的输入输出流和客户端实现数据交换
    4. 完成操作后关闭输入输出流、Socket、ServerSocket释放资源
  • 示例代码(服务器端接收客户端发送的信息,并把接收到的信息返回给客户端)
  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6. import java.nio.charset.StandardCharsets;
  7. public class ServerDemo {
  8. public static void main(String[] args) throws IOException {
  9. //创建服务器端ServerSocket对象,并指定端口
  10. ServerSocket serverSocket = new ServerSocket(9999);
  11. //监听此端口并接受返回Socket对象
  12. Socket socket = serverSocket.accept();
  13. //获取链接的输入流 读数据 客户端-->服务端
  14. InputStream is = socket.getInputStream();
  15. byte[] bytes = new byte[1024];
  16. int len = is.read(bytes);
  17. String data = new String(bytes, 0, len);
  18. System.out.println("服务器------> 客户端:"+data);
  19. //获取流的输出流 服务端-->客户端
  20. OutputStream os = socket.getOutputStream();
  21. //返回客户端发送过来的数据
  22. String sentData = "数据已收到---->" + data;
  23. os.write(sentData.getBytes(StandardCharsets.UTF_8));
  24. //释放资源
  25. is.close();
  26. os.close();
  27. socket.close();
  28. }
  29. }