java 网络编程

来源:互联网 发布:unity3d场景制作 编辑:程序博客网 时间:2024/06/01 16:36

网络编程的目的

网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通信。网络编程中主要的两个问题:1、如何准确的定位网络上的一台或多台主机。2、找到主机后如何进行可靠高效的数据传输。

网络通讯要输

  1. IP地址
  2. 端口号
  3. 传输协议

IP地址

  • 网络中的每一台主机都有唯一的IP地址
  • 因特网上的IP地址具有全球唯一性
  • IP地址有32位二进制组成,占4个字节,常用十进制表示,例如192.168.0.1
  • 对应的类-InetAddress

端口号

  • 端口号用来表示该计算机的应用程序,代表此应用程序逻辑地址
  • 端口号使用一个16位的数字来表示,范围是0~65535,1024以内的端口号保留给预定的服务。例如:http协议使用80端口

传输协议

  • TCP协议,是一个可靠的传输协议
  • UDP协议,数据包传输协议,能否送达目的地不确定。是一种无连接的协议。
    对传输的精确度要求高的话使用TCP协议,如果对精确度要求不高,追求速度的话使用UDP协议

Socket

  • socket通常也被称为“套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过“套接字”向网络发出请求或者应答网络请求。
  • socket是连接运行在网络上两个程序间的双向通讯的端点。
  • 网络通讯其实指的就是Socket间的通讯。
  • 通讯的两端都有Socket,数据在两个Socket之间通过IO来进行传输

使用Socket进行网络通信的过程

  1. 服务程序将一个套接字绑定到一个特定的端口,并通过此套接字等待和监听客户端的连接请求。
  2. 客户端根据服务端程序所在的主机id和端口号通过Socket发出连接请求
  3. 客户端和服务器通过读、写题套接字进行通讯
    简单描述如下图:
    这里写图片描述

基于TCP协议的Socket编程

基本流程图
这里写图片描述
从中不难看出:客户端的输入流对应服务端的输出流,服务端的输出流对应客户端的输入流

创建Tcp服务端步骤:

  1. 创建一个ServerSocket对象
  2. 调用accept()方法接受客户端套接字请求
  3. 从Socket中获取I/O流
  4. 对I/O流进行读写操作,完成与客户端的交互。
  5. 关闭I/O流和ServerSocket
package tcpSocket;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class TCPServer {    public static void main(String[] args) throws IOException {        //1、创建ServerSocket对象        ServerSocket serverSocket = new ServerSocket(8888);        //2、调用accept()方法接收客户端的请求        Socket socket = serverSocket.accept();        System.out.println(socket.getInetAddress().getHostAddress()+"has connection!");        //3、获取socket对象的输入输出流        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));//      BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));        PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);        String line = null;        //4、对流进行读写操作,与客户端完成交互        //读取客户端传过来的数据        while((line = br.readLine()) != null){            if(line.equals("over")){                break;            }            System.out.println(line);//将度过来的数据打印一下//          bw.write(line.toUpperCase());//将读取的信息转化为大写写给客户端//          bw.newLine();//换行//          bw.flush();            pw.println(line.toUpperCase());//这一行代替上面三行,总之用PrintWriter简单点        }//      bw.close();        //5、关闭I/O流和ServerSocket        br.close();        pw.close();        socket.close();        System.out.println(socket.getInetAddress().getHostAddress()+"has closed!");    }}

创建TCP客户端步骤:

  1. 创建一个Socket对象
  2. 从Socket中获取I/O流
  3. 对I/O流进行读写操作,完成无服务端的交互。
  4. 关闭I/O流和Socket
package tcpSocket;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.Socket;import java.net.UnknownHostException;public class TCPClient {    public static void main(String[] args) throws UnknownHostException, IOException {        //1、创建Socket对象        Socket socket = new Socket("127.0.0.1",8888);        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        //2、从Socket对象中获取I/O流//      BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));        PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);        //3、对流进行读写操作,与服务端完成交互        while(true){            String line = br.readLine();//从键盘上输入的字符//          bw.write(line);//          bw.newLine();//换行//          bw.flush();            pw.println(line);//将数据写给服务端            if(line.equals("over")){                break;            }            System.out.println(reader.readLine());//打印出从服务端读取的信息        }        //4、关闭I/O流和Socket        reader.close();        br.close();//      bw.close();        pw.close();        socket.close();    }}

最后启动TCPSokcet后,再启动TCPClient运行后的结果如下:
服务端:
这里写图片描述
客户端:
这里写图片描述

基于UDP协议的Socket编程

创建发送端

  1. 建立DatagramSocket对象。该端点建立,系统会随机分配一个端口。如果不想随机配置,可以手动指定。
  2. 将数据进行packet包的封装,必须要指定目的地地址和端口。
  3. 通过socket服务的send方法将该包发出。
  4. 将socket关闭

创建接收端

  1. 建立DatagramSocket对象。要监听一个端口。
  2. 通过socket的receive方法将数据存入数据包中
  3. 通过数据包dp的方法getData()、getAddress()、getPort()等方法获取包中的指定信息。
  4. 将socket关闭

程序例子

package udpsocket;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class UDPDemo1 {    public static void main(String[] args) throws IOException {        //1、建立DatagramSocket对象        DatagramSocket socket = new DatagramSocket();//无参的系统会随机分配一个端口        String str = "I love you!";        //2、把数据进行封装,封装到数据包中(数据包中包括发送的数据、数据长度、目的地和端口号)        DatagramPacket packet = new DatagramPacket(str.getBytes(), str.length(),InetAddress.getByName("localhost"),8000);        //3、通过socket服务的send方法发出包        socket.send(packet);//发送        byte [] buff = new byte[100];//一个大小为100的字节数组用来接收数据        DatagramPacket packet2 = new DatagramPacket(buff, 100);        socket.receive(packet2);//接收数据        System.out.println(new String(packet2.getData()));        //关闭socket        socket.close();    }}
package udpsocket;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;public class UDPDemo2 {    public static void main(String[] args) throws IOException{        DatagramSocket socket = new DatagramSocket(8000);        byte [] buff = new byte[100];        DatagramPacket packet = new DatagramPacket(buff,100);        socket.receive(packet);//接收传来的数据包        System.out.println(new String(packet.getData()));        String str = "Me too!";        DatagramPacket packet2 = new DatagramPacket(str.getBytes(), str.length(), packet.getAddress(), packet.getPort());        socket.send(packet2);        socket.close();    }}

先运行UDPDemo2再运行UDPDemo1结果为:
UDPDemo1控制台输出:Mee to!
UDPDemo2控制台输出:I love you!