摘要:本文主要介绍了什么是网络编程,以及如何使用Java语言进行网络编程。
部分内容来自以下博客:
https://www.cnblogs.com/renyuan/p/2698779.html
https://blog.csdn.net/qq_35860138/article/details/82054793
https://segmentfault.com/a/1190000018582150
https://www.cnblogs.com/kuangzhisen/p/7053689.html
网络编程就是在两个或两个以上的设备之间传输数据。程序员所作的事情就是把数据发送到指定的位置,或者接收到指定的数据,这个就是狭义的网络编程范畴。在发送和接收数据时,大部分的程序设计语言都设计了专门的API实现这些功能,程序员只需要调用即可。
网络编程的基本模型就是客户机到服务器模型,简单的说就是两个进程之间相互通讯,然后其中一个必须提供一个固定的位置,而另一个则只需要知道这个固定的位置。并去建立两者之间的联系,然后完成数据的通讯就可以了,这里提供固定位置的通常称为服务器,而建立联系的通常叫做客户端。
Java是Internet上的语言,它从语言级上提供了对网络应用程序的支持,程序员能够很容易开发常见的网络应用程序。
Java提供的网络类库,可以实现无痛的网络连接,联网的底层细节被隐藏在Java的本机安装系统里,由JVM进行控制。并且Java实现了一个跨平台的网络库,程序员面对的是一个统一的网络编程环境。
把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统。
从而使众多的计算机可以方便地互相传递信息、共享硬件、软件、数据信息等资源。
直接或间接地通过网络协议与其它计算机进行通讯。
如何准确地定位网络上一台或多台主机,如何定位主机上的特定的应用。
找到主机后如何可靠高效地进行数据传输。
1)通信双方的地址:
IP地址和端口号。
2)一定的规则,即网络通讯协议,有两套参考模型:
OSI参考模型:模型过于理想化,未能在因特网上进行广泛推广。
TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。
为了能够方便的识别网络上的每个设备,网络中的每个设备都会有一个唯一的数字标识,这个就是IP地址。
由于IP地址不容易记忆,所以为了方便记忆,有创造了另外一个概念:域名(Domain Name),例如sohu.com等。一个IP地址可以对应多个域名,一个域名只能对应一个IP地址。
在网络中传输的数据,全部是以IP地址作为地址标识,所以在实际传输数据以前需要将域名转换为IP地址,实现这种功能的服务器称之为DNS服务器,也就是通俗的说法叫做域名解析。例如当用户在浏览器输入域名时,浏览器首先请求DNS服务器,将域名转换为IP地址,然后将转换后的IP地址反馈给浏览器,然后再进行实际的数据传输。
IP地址和域名很好的解决了在网络中找到一个计算机的问题,但是为了解决在网络中找到一个计算机上的特定应用的问题,就引入了另外一个概念:端口(Port)。
在同一个计算机中每个程序对应唯一的端口,这样一个计算机上就可以通过端口区分发送给每个端口的数据了,换句话说,也就是一个计算机上可以并发运行多个网络程序,而不会在互相之间产生干扰。
有了IP地址和端口的概念以后,在进行网络通讯交换时,就可以通过IP地址查找到该台计算机,然后通过端口标识这台计算机上的一个唯一的程序,这样就可以进行网络数据的交换了。
最后再介绍一个网络编程中最重要,也是最复杂的概念:协议(Protocol)。
按照前面的介绍,网络编程就是运行在不同计算机中两个程序之间的数据交换。在实际进行数据交换时,为了让接收端理解该数据,计算机比较笨,什么都不懂的,那么就需要规定该数据的格式,这个数据的格式就是协议。
TCP/IP以其两个主要协议:传输控制协议(TCP)和网络互联协议(IP)而得名,实际上是一组协议,包括多个具有不同功能且互为关联的协议。
TCP/IP协议模型从更实用的角度出发,形成了高效的四层体系结构,即:网络接口层、网络层、传输层和应用层。
应用层:
TCP/IP模型将OSI参考模型中的会话层和表示层的功能合并到应用层实现。
应用层面向不同的网络应用引入了不同的应用层协议。其中,有基于TCP协议的,如文件传输协议(File Transfer Protocol,FTP)、虚拟终端协议(TELNET)、超文本链接协议(Hyper Text Transfer Protocol,HTTP)等。也有基于UDP协议的,如网络文件系统(Network File System,NFS)、简单网络管理协议(Simple Network Management Protocol,SNMP)、主域名称系统(Domain Name System,DNS)、通用文件传输协议(Trivial File Transfer Protocol,TFTP)等。
传输层:
在TCP/IP模型中,传输层的功能是使源端主机和目标端主机上的对等实体可以进行会话。在传输层定义了两种服务质量不同的协议,即:传输控制协议TCP(transmission control protocol)和用户数据报协议UDP(user datagram protocol)。
TCP协议是一个面向连接的、可靠的协议。它将一台主机发出的字节流无差错地发往互联网上的其他主机。在发送端,它负责把上层传送下来的字节流分成报文段并传递给下层。在接收端,它负责把收到的报文进行重组后递交给上层。TCP协议还要处理端到端的流量控制,以避免缓慢接收的接收方没有足够的缓冲区接收发送方发送的大量数据。
UDP协议是一个不可靠的、无连接协议,主要适用于不需要对报文进行排序和流量控制的场合。
互连网络层:
网络互连层是整个TCP/IP协议栈的核心。它的功能是把分组发往目标网络或主机。同时,为了尽快地发送分组,可能需要沿不同的路径同时进行分组传递。因此,分组到达的顺序和发送的顺序可能不同,这就需要上层必须对分组进行排序。
网络互连层定义了分组格式和协议,即IP协议(Internet Protocol)。
网络互连层除了需要完成路由的功能外,也可以完成将不同类型的网络(异构网)互连的任务。除此之外,网络互连层还需要完成拥塞控制的功能。
网络接口层(主机到网络层):
实际上TCP/IP参考模型没有真正描述这一层的实现,只是要求能够提供给其上层一个访问接口,以便在其上传递IP分组。由于这一层次未被定义,所以其具体的实现方法将随着网络类型的不同而不同。
客户端首先向服务端发送请求报文。
服务端收到请求报文后,发送响应报文和服务端的请求报文。
客户端收到服务端的响应报文和请求报文后,回传给服务端响应报文,进入连接建立状态。
服务端在收到客户端的响应报文后,也进入了连接状态。
客户端首先向服务端发送请求关闭报文。
服务端收到请求关闭报文后,发送响应关闭报文。
客户端收到服务端的响应报文后,进入等待关闭状态,停止数据发送。服务端在此期间继续处理残余报文,等到处理完毕之后,向客户端发送请求关闭报文。
客户端收到服务端的请求关闭报文后,回传给服务端响应关闭报文。
服务端在收到客户端的响应关闭报文后,进入了连接关闭状态。
java.net.InetAddress:此类表示互联网协议(IP)地址。
常用方法:
public static InetAddress getByName(String host):根据IP地址或者域名获取InetAddress实例。
public static InetAddress getLocalHost():获取IP地址为本地的InetAddress实例。
public String getHostName():获取InetAddress实例的主机名。
public String getHostAddress():获取InetAddress实例的IP地址。
测试代码:
1 public static void main(String[] args) { 2 try { 3 InetAddress baidu = InetAddress.getByName("www.baidu.com"); 4 InetAddress local = InetAddress.getLocalHost(); 5 System.out.println(baidu.getHostName()); 6 System.out.println(local.getHostAddress()); 7 } catch (UnknownHostException e) { 8 e.printStackTrace(); 9 } 10 }
运行结果:
1 www.baidu.com 2 192.168.1.109
java.net.InetSocketAddress:此类实现IP套接字地址(IP地址和端口号)。
构造方法:
public InetSocketAddress(int port):根据端口创建本地套接字地址。
public InetSocketAddress(InetAddress addr, int port):根据IP地址和端口号创建套接字地址。
public InetSocketAddress(String hostname, int port):根据主机名和端口号创建套接字地址。
常用方法:
public final InetAddress getAddress():获取InetAddress实例。
public final String getHostName():获取主机名。
public final int getPort():获取端口号。
public String toString():构造此InetSocketAddress的字符串表示形式(主机名/IP:端口号)。
测试代码:
1 public static void main(String[] args) { 2 try { 3 InetSocketAddress local = new InetSocketAddress(InetAddress.getLocalHost(), 80); 4 InetSocketAddress baidu = new InetSocketAddress("www.baidu.com", 80); 5 System.out.println(baidu); 6 System.out.println(baidu.getHostName()); 7 System.out.println(local.getAddress().getHostAddress()); 8 System.out.println(local.getPort()); 9 } catch (UnknownHostException e) { 10 e.printStackTrace(); 11 } 12 }
运行结果:
1 www.baidu.com/182.61.200.7:80 2 www.baidu.com 3 192.168.1.109 4 80
java.net.Socket:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
构造方法:
public Socket(InetAddress address, int port):创建一个流套接字并将其连接到指定IP地址的指定端口号。
public Socket(String host, int port):创建一个流套接字并将其连接到指定主机上的指定端口号。
常用方法:
public OutputStream getOutputStream():返回此套接字的输出流。
public InputStream getInputStream():返回此套接字的输入流。
public void close():关闭此套接字。
java.net.ServerSocket:此类实现服务器套接字。服务器套接字等待请求通过网络传入。
构造方法:
public ServerSocket(int port):创建绑定到特定端口的服务器套接字。
常用方法:
public Socket accept():侦听并接受到此套接字的连接。
public void close():关闭此套接字。
java.net.DatagramSocket:此类表示用来发送和接收数据报包的套接字。
构造方法:
public DatagramSocket():创建数据报套接字,将其绑定到本地地址上的默认0号端口。
public DatagramSocket(int port):创建数据报套接字,将其绑定到本地地址上的指定端口。
public DatagramSocket(int port, InetAddress laddr):创建数据报套接字,将其绑定到指定地址上的指定端口。
常用方法:
public void send(DatagramPacket p):从此套接字发送数据报包。
public synchronized void receive(DatagramPacket p):从此套接字接收数据报包。
public void close():关闭此数据报套接字。
java.net.DatagramPacket:此类表示数据报包。
构造方法:
public DatagramPacket(byte buf[], int length):用来接收数据包。
public DatagramPacket(byte buf[], int offset, int length):用来接收数据包。
public DatagramPacket(byte buf[], int length, InetAddress address, int port):用来将数据包发送到指定主机上的指定端口。
public DatagramPacket(byte buf[], int offset, int length, InetAddress address, int port):用来将数据包发送到指定主机上的指定端口。
客户端代码:
1 public static void main(String[] args) { 2 Socket s = null; 3 OutputStream os = null; 4 try { 5 System.out.println("客户端已启动"); 6 s = new Socket(InetAddress.getLocalHost(), 8800); 7 os = s.getOutputStream(); 8 os.write("你好,我是客户端".getBytes()); 9 System.out.println("客户端成功发送数据"); 10 } catch (IOException e) { 11 e.printStackTrace(); 12 } finally { 13 if (os != null) { 14 try { 15 os.close(); 16 } catch (IOException e) { 17 e.printStackTrace(); 18 } 19 } 20 if (s != null) { 21 try { 22 s.close(); 23 } catch (IOException e) { 24 e.printStackTrace(); 25 } 26 } 27 } 28 }
服务端代码:
1 public static void main(String[] args) { 2 ServerSocket ss = null; 3 Socket s = null; 4 InputStream is = null; 5 ByteArrayOutputStream baos = null; 6 try { 7 System.out.println("服务端已启动"); 8 ss = new ServerSocket(8800); 9 s = ss.accept(); 10 is = s.getInputStream(); 11 byte[] temp = new byte[1024]; 12 int len; 13 baos = new ByteArrayOutputStream(); 14 while ((len = is.read(temp)) != -1) { 15 baos.write(temp, 0, len); 16 } 17 System.out.println("服务端成功接收数据:" + baos.toString()); 18 } catch (IOException e) { 19 e.printStackTrace(); 20 } finally { 21 if (baos != null) { 22 try { 23 baos.close(); 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } 27 } 28 if (is != null) { 29 try { 30 is.close(); 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 } 35 if (s != null) { 36 try { 37 s.close(); 38 } catch (IOException e) { 39 e.printStackTrace(); 40 } 41 } 42 if (ss != null) { 43 try { 44 ss.close(); 45 } catch (IOException e) { 46 e.printStackTrace(); 47 } 48 } 49 } 50 }
客户端结果:
1 客户端已启动 2 客户端成功发送数据
服务端结果:
1 服务端已启动 2 服务端成功接收数据:你好,我是客户端
客户端代码:
1 public static void main(String[] args) { 2 Socket s = null; 3 OutputStream os = null; 4 InputStream is = null; 5 ByteArrayOutputStream baos = null; 6 try { 7 System.out.println("客户端已启动"); 8 s = new Socket(InetAddress.getLocalHost(), 8800); 9 os = s.getOutputStream(); 10 os.write("你好,我是客户端".getBytes()); 11 System.out.println("客户端成功发送数据"); 12 s.shutdownOutput(); 13 14 is = s.getInputStream(); 15 byte[] temp = new byte[1024]; 16 int len; 17 baos = new ByteArrayOutputStream(); 18 while ((len = is.read(temp)) != -1) { 19 baos.write(temp, 0, len); 20 } 21 System.out.println("客户端成功接收服务端回传数据:" + baos.toString()); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 } finally { 25 if (os != null) { 26 try { 27 os.close(); 28 } catch (IOException e) { 29 e.printStackTrace(); 30 } 31 } 32 if (s != null) { 33 try { 34 s.close(); 35 } catch (IOException e) { 36 e.printStackTrace(); 37 } 38 } 39 if (baos != null) { 40 try { 41 baos.close(); 42 } catch (IOException e) { 43 e.printStackTrace(); 44 } 45 } 46 if (is != null) { 47 try { 48 is.close(); 49 } catch (IOException e) { 50 e.printStackTrace(); 51 } 52 } 53 } 54 }
服务端代码:
1 public static void main(String[] args) { 2 ServerSocket ss = null; 3 Socket s = null; 4 InputStream is = null; 5 ByteArrayOutputStream baos = null; 6 OutputStream os = null; 7 try { 8 System.out.println("服务端已启动"); 9 ss = new ServerSocket(8800); 10 s = ss.accept(); 11 is = s.getInputStream(); 12 byte[] temp = new byte[1024]; 13 int len; 14 baos = new ByteArrayOutputStream(); 15 while ((len = is.read(temp)) != -1) { 16 baos.write(temp, 0, len); 17 } 18 System.out.println("服务端成功接收数据:" + baos.toString()); 19 20 os = s.getOutputStream(); 21 os.write("你好,我是服务端".getBytes()); 22 System.out.println("服务端成功发送回传数据"); 23 } catch (IOException e) { 24 e.printStackTrace(); 25 } finally { 26 if (baos != null) { 27 try { 28 baos.close(); 29 } catch (IOException e) { 30 e.printStackTrace(); 31 } 32 } 33 if (is != null) { 34 try { 35 is.close(); 36 } catch (IOException e) { 37 e.printStackTrace(); 38 } 39 } 40 if (s != null) { 41 try { 42 s.close(); 43 } catch (IOException e) { 44 e.printStackTrace(); 45 } 46 } 47 if (ss != null) { 48 try { 49 ss.close(); 50 } catch (IOException e) { 51 e.printStackTrace(); 52 } 53 } 54 if (os != null) { 55 try { 56 os.close(); 57 } catch (IOException e) { 58 e.printStackTrace(); 59 } 60 } 61 } 62 }
客户端结果:
1 客户端已启动 2 客户端成功发送数据 3 客户端成功接收服务端回传数据:你好,我是服务端
服务端结果:
1 服务端已启动 2 服务端成功接收数据:你好,我是客户端 3 服务端成功发送回传数据
客户端代码:
1 public static void main(String[] args) { 2 try { 3 System.out.println("客户端已启动"); 4 DatagramSocket ds = new DatagramSocket(); 5 byte[] buffer = "我是客户端".getBytes(); 6 DatagramPacket dp = new DatagramPacket(buffer, 0, buffer.length, InetAddress.getLocalHost(), 8800); 7 ds.send(dp); 8 System.out.println("客户端成功发送数据"); 9 ds.close(); 10 } catch (IOException e) { 11 e.printStackTrace(); 12 } 13 }
服务端代码:
1 public static void main(String[] args) { 2 try { 3 System.out.println("服务端已启动"); 4 DatagramSocket ds = new DatagramSocket(8800); 5 byte[] buffer = new byte[1024]; 6 DatagramPacket dp = new DatagramPacket(buffer , 0, buffer.length); 7 ds.receive(dp); 8 System.out.println("服务端成功接收数据:" + new String(dp.getData(), 0, dp.getLength())); 9 ds.close(); 10 } catch (IOException e) { 11 e.printStackTrace(); 12 } 13 }
客户端结果:
1 客户端已启动 2 客户端成功发送数据
服务端结果:
1 服务端已启动 2 服务端成功接收数据:我是客户端
客户端代码:
1 public static void main(String[] args) { 2 try { 3 System.out.println("顾客已上线"); 4 Scanner scan = new Scanner(System.in); 5 DatagramSocket ds = new DatagramSocket(8811); 6 while (true) { 7 String message = scan.next(); 8 byte[] bufMes = message.getBytes(); 9 DatagramPacket dpMes = new DatagramPacket(bufMes, 0, bufMes.length, InetAddress.getLocalHost(), 8800); 10 ds.send(dpMes); 11 12 byte[] bufRec = new byte[1024]; 13 DatagramPacket dpRec = new DatagramPacket(bufRec , 0, bufRec.length); 14 ds.receive(dpRec); 15 String receive = new String(dpRec.getData(), 0, dpRec.getLength()); 16 System.out.println("客服说:" + receive); 17 18 if (message.equals("bye")) { 19 break; 20 } 21 } 22 scan.close(); 23 ds.close(); 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } 27 }
服务端代码:
1 public static void main(String[] args) { 2 try { 3 System.out.println("客服已上线"); 4 Scanner scan = new Scanner(System.in); 5 DatagramSocket ds = new DatagramSocket(8800); 6 while (true) { 7 byte[] bufRec = new byte[1024]; 8 DatagramPacket dpRec = new DatagramPacket(bufRec , 0, bufRec.length); 9 ds.receive(dpRec); 10 String receive = new String(dpRec.getData(), 0, dpRec.getLength()); 11 System.out.println("顾客说:" + receive); 12 13 String message = scan.next(); 14 byte[] bufMes = message.getBytes(); 15 DatagramPacket dpMes = new DatagramPacket(bufMes, 0, bufMes.length, InetAddress.getLocalHost(), 8811); 16 ds.send(dpMes); 17 18 if (message.equals("bye")) { 19 break; 20 } 21 } 22 scan.close(); 23 ds.close(); 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } 27 }
客户端结果:
服务端结果:
URL编程
原文:https://www.cnblogs.com/shamao/p/10977326.html