欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java学习笔记(十五)java网络编程

程序员文章站 2022-07-12 08:03:45
...

OSI模型分为七层(从下到上):物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

不同主机之间的相同层次称为对等层。对等层之间互相通信需要遵守一定的规则,称之为协议,我们将某个主机上运行的某种协议的集合称为协议栈。主机正是利用这个协议栈来接收和发送数据的。

TCP/IP模型:网络接口层、网络互连层、传输层、应用层。

在网络编程中需要注意的问题包括:

1.是如何找到网络上的主机上的要进行通讯的程序;

2.是找到了主机上的程序后如何传输数据。

端口号:是一组16位的无符号二进制数,每个端口号的范围是1到65535(0被保留)。

TCP协议代表传输控制协议,允许两个应用程序之间的进行可靠的通讯;

UDP协议代表用户报文协议,是一种非连接协议,允许两个应用程序之间进行不可靠的通讯。提供了在应用程序之间发送称为数据报的协议。

Socket套接字:Unix系统推出了一种应用程序访问通信协议的操作系统调用,是一种抽象层,应用程序通过它来发送和接收数据。

不同类型的Socket与不同类型的底层协议族以及同一协议族中的不同协议栈相关联。

InetAddress类代表IP地址,例:

import java.net.InetAddress;

public class InetAddressTest {

        public static void main(String[] args) throws Exception {
	       InetAddress ip = InetAddress.getLocalHost();
	       System.out.println(ip);
	       InetAddress ip = InetAddress.getByName("80YMEKCC96RXAOB");
	       System.out.println(ip);
	       InetAddress[] allByName = InetAddress.getAllByName("www.baidu.com");
	      for (InetAddress inetAddress : allByName) {
	            System.out.println(inetAddress);
	       }
             byte[] ip = {(byte)192, (byte)168, 1, 52};
             InetAddress address = InetAddress.getByAddress("www.baidu.com", ip);
             System.out.println(address);
      }
}

  

使用套接字建立TCP连接:

1.服务器初始化一个ServerSocket对象,指示通讯将要发生在哪个端口号上。

2.服务器调用ServerSocket类的accept()方法。该方法会一直等待,直到一个客户端连接到服务器上的指定端口。

3.在服务器等待的同时,客户端实例化一个Socket对象,指定要连接的服务器名和端口号。

4.Socket类的构造器试图将客户端连接到指定的服务器和端口号。

5.在服务器端,accept()方法返回一个将要连接到客户端套接字的服务器新套接字的引用。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
* 服务器端
* 
* @author Administrator
*
*/
public class Server {

     public static void main(String[] args) throws IOException {
           // 创建ServerSocket对象,指定监听端口
           ServerSocket server = new ServerSocket(30001);
           // 设置超时时间
           server.setSoTimeout(10000);
           // 等待客户端连接
           Socket socket = server.accept();
            /* 处理客户端数据 */
           // 从客户端读数据
           BufferedReader reader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
           char[] ch = new char[100];
            int len = reader.read(ch);
            System.out.println("从客户端接收到的信息:");
            // while (-1 != (len = reader.read(ch))) {
            System.out.print(new String(ch, 0, len));
            // }
           // 向客户端写数据
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream()));
            writer.write("你好客户端,我已经接收到你的信息了");
            writer.flush();
              // 释放资源
            writer.close();
             reader.close();
             socket.close();
             server.close();
        }
}

  

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/**
* 客户端 请求--响应
* 
* @author Administrator
*
*/
public class Client {

        public static void main(String[] args) throws IOException {
              // 创建客户端Socket向服务器发起连接请求
             Socket socket = new Socket("192.168.1.200", 30001);
             /* 利用已建立的socket创建输入输出流,处理与服务器端的连接 */
             // 向服务器写入数据
          BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
           socket.getOutputStream()));
           writer.write("你好服务器!!!");
            writer.flush();
          // 从服务器读数据
          BufferedReader reader = new BufferedReader(new  InputStreamReader(
socket.getInputStream()));
           char[] ch = new char[100];
           int len = reader.read(ch);
           System.out.println("从服务器端接收到的信息:");
            // while (-1 != (len = reader.read(ch))) {
            System.out.print(new String(ch, 0, len));
           // }
         // 释放资源
          reader.close();
          writer.close();
           socket.close();
        }
}

  

 

UDP套接字编程

数据报包的发送者和接受者都使用java.net.DatagramSocket类分别发送和接收包。

接收报文包:

1.创建一个足够大的字节数组,用于存储要接收的包的数据;

2.使用该字节数组实例化一个DatagramPacket对象;

3.DatagramSocket被实例化,它被指定该套接字要绑定到的本地主机上的一个端口;

4.调用DatagramSocket类的receive()方法,将DatagramPacket对象传入该方法。这将导致执行线程阻塞,直到接收到一个数据报包或者发生了超时。

import java.net.*;
import java.io.*; 

public class PacketReceiver{

     public static void main(String[] args) {
            try{
                   byte[] buffer = new byte [1024];
                   DatagramOacket packet = new DatagramPacket(buffer,buffer.length);
                   DatagramSocket socket = new DatagramSocket(5002);
                   Syatem.out.println("正在等待一个包...");
                   socket.receive(packet);
                   System.out.println("刚从" + packet.getSocketAddress() + "接收到包");
                   buffer = packet.getData();
                   System.out.println("new String(buffer)");
            } catch(IOException e){
                    e.printStackTrace();
            }
     } 
}

发送报文包

1.创建一个足够大的字节数组,用于存储要发送的包数据,用该数据填充数组;

2.创建一个新的DatagramPacket对象,用于存储上面的字节数组,以及服务器名和接受者的端口号;

3.DatagramSocket被实例化,它被指定套接字要绑定到本地主机的哪个端口;

4.DatagramSocket类的send()方法被调用,传入DatagramPacket对象。

import java.net.*;
import java.io.*;

public class PacketSender{
       public static void main(String [] args){
                 try{
                       String data = "刚收到数据包";
                       byte[] buffer = data.getBytes();
                       DatagramPacket packet = new DatagramPacket(buffer,buffer.length,new InetSocketAddress("localhost",5002));
                       DatagramSocket socket = new DatagramSocket(5003);
                       System.out.println("正在发送一个包...");
                       Socket.send(packet);
                 } catch(IOException e){
                       e.printStackTrace();
                 }
        }
}