Java 网络编程

1.UDP

UDP是面向无连接的,所以发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。而且由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,但是由于UDP的面向无连接性,不能保证数据的完整性,偶尔会丢失一两个包,因此在传输重要数据时,不建议使用UDP协议。
特点:数据被限制在64kb以内,超出这个范围就不能发送了。

2.TCP

TCP是面向连接的,在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。
1.客户端向服务器端发出连接请求,等待服务器确认。
2.服务器端向客户端回送一个响应,通知客户端收到了连接请求。
3.客户端再次向服务器端发送确认信息,确认连接。

其次,TCP的客户端和服务端断开连接,需要四次挥手

InetAddress的使用

InetAddress类无构造方法

  1. bash byte[] getAddress()返回此 InetAddress 对象的原始 IP 地址。

  2. bash static InetAddress getByName(String host)在给定主机名的情况下确定主机的 IP 地址。

  3. bash String getHostAddress()返回 IP 地址字符串(以文本表现形式)。

  4. bash String getHostName()获取此 IP 地址的主机名。

  5. bash static InetAddress getLocalHost()返回本地主机。(域名/IP地址)

127.0.0.1:本机地址,主要用于测试。别名:Localhost

public class test{
    public static void main(String[] args) throws Exception {
        InetAddress ip1=InetAddress.getByName("www.baidu.com"); //如果是IP地址的话就只能解析出ip地址
        System.out.println(ip1.getHostName());//www.baidu.com
        System.out.println(ip1.getHostAddress());//183.232.231.174
      System.out.println(ip1.getAddress());//[B@1b6d3586
       System.out.println(ip1.getLocalHost());//采荼薪樗/192.168.3.229
    }
}

DatagramPacket类、DatagramSocket类放在java.net包中

1.DatagramSocket. 构造方法摘要

  1. protected DatagramSocket()构造数据报套接字并将其绑定到本地主机上的任何可用端口。
  2. protected DatagramSocket(int port)构造数据报套接字并将其绑定到本地主机上的指定端口。
  3. protected DatagramSocket(int port, InetAddress laddr)创建一个数据报套接字,绑定到指定的本地地址。

2.DatagramPacket

(1)构造方法摘要

  1. DatagramPacket(byte[] buf, int offset, int length)构造一个 DatagramPacket用于接收指定长度的数据报包到缓冲区中。
  2. DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)构造用于发送指定长度的数据报包到指定主机的指定端口号上。

(2)常用方法摘要
byte[] getData() 返回数据报包中的数据。
InetAddress getAddress() 返回该数据报发送或接收数据报的计算机的IP地址。
int getLength() 返回要发送的数据的长度或接收到的数据的长度。

UDP网络编程

//客户发送端
public class Inet {
    public static void main(String[] args) throws IOException {
      //创建发送端的接口
        DatagramSocket ds=new DatagramSocket();
        //创建发送端的数据包
       byte[]b="服务器你好呀,我来自客户端".getBytes();
       DatagramPacket dp=new DatagramPacket(b,b.length,InetAddress.getByName("localhost"),1024);
        //发送数据包
        ds.send(dp);
         ds.close();
    }
}

//服务器接收端
public class Server {
    public static void main(String[] args) throws  Exception{
       //创建接收端接口
        DatagramSocket ds =new DatagramSocket(1024);
        //创建一个接收包
        byte[]b=new byte[1024];
        DatagramPacket dp=new DatagramPacket(b,b.length);
        //接受数据包
        ds.receive(dp);
        //获取发送端的IP地址以及数据
        String ip=dp.getAddress().getHostAddress();
        String data=new String(dp.getData(),0,dp.getLength()); //获取包中的数据段转化成字符串
        System.out.println("from"+ip+":"+data);

    }
}

public class Client {
    public static void main(String[] args)throws  Exception {
        //创建Socket对象,连接服务器
        Socket socket =new Socket("localhost",9999);
        System.out.println("客户端向服务器连接成功");
        //2.从客户端发送数据给服务器
        Scanner sc=new Scanner(System.in);
        while(true)
        {
            OutputStream os =socket.getOutputStream();
            BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os));//字节流转化为字符流
            bw.write(sc.nextLine());
            bw.newLine();
            bw.flush();
            //客户端接收数据
            InputStream in= socket.getInputStream();
            BufferedReader br=new BufferedReader(new InputStreamReader(in));
            String content=br.readLine();
            System.out.println("从服务器发送来的数据是:"+content);
        }


    }
}
class Server {
    public static void main(String[] args) throws  Exception{
        //1.创建服务器端对象
        ServerSocket ss=new ServerSocket(9999);
        System.out.println("服务器正在等待连接");
        //2.等待客户端连接
        Socket s=ss.accept();  //先跑服务器,阻塞,再跑客户端
        System.out.println("服务器已与客户端连接成功");
        Scanner sc=new Scanner(System.in);
        while(true)
        {
            InputStream in=s.getInputStream();
            BufferedReader br=new BufferedReader(new InputStreamReader(in));
            String content=br.readLine();
            System.out.println("客户端传过来"+content);
            //服务器发送数据
            OutputStream os=s.getOutputStream();
            BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os));
            bw.write(sc.nextLine());
            bw.newLine();
            bw.flush();
        }

    }
}

ByteArrayOutputStream 对byte类型数据进行写入的类 相当于一个中间缓冲层,将类写入到文件等其他outputStream。它是对字节进行操作,属于内存操作流

TCP网络编程

1.Socket类

Socket 类:该类实现客户端套接字,套接字指的是两台设备之间通讯的端点。

(1)构造方法摘要

  • public Socket(String host, int port)**创建套接字对象并将其连接到指定主机上的指定端口号。如果指定的host是null ,则相当于指定地址为回送地址。
 //创建发送端接口
        Socket s=new Socket("127.0.0.1",8888);

(2)常用方法摘要

  • public InputStream getInputStream() : 返回此套接字的输入流。

如果此Scoket具有相关联的通道,则生成的InputStream 的所有操作也关联该通道。
关闭生成的InputStream也将关闭相关的Socket。

  • public OutputStream getOutputStream() : 返回此套接字的输出流。

如果此Scoket具有相关联的通道,则生成的OutputStream 的所有操作也关联该通道。
关闭生成的OutputStream也将关闭相关的Socket。

  • public void shutdownOutput() : 任何先前写出的数据将被发送,随后终止输出流。用来提示服务器,我客户端已经发送数据结束了

  • public void close() :关闭此套接字。
    一旦一个socket被关闭,它不可再使用。
    关闭此socket也将关闭相关的InputStream和OutputStream 。

2.ServerSocket类

ServerSocket类:这个类实现了服务器套接字,该对象等待通过网络的请求。

(1)构造方法摘要

  • public ServerSocket(int port) :使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上,参数port就是端口号。

(2)常用方法摘要

  • public Socket accept() :侦听并接受连接,返回一个新的Socket对象,用于和客户端实现通信。该方法会一直阻塞直到建立连接。
 ServerSocket recive =new ServerSocket(8888); //创建服务器接口,指明自己的端口号
        Socket socket=recive.accept(); // 阻塞式监听客户端的接入

演示案例:
客户端

public class TCPsend {  //TCP要保证数据被收到所以要先开启服务器
    public static void main(String[] args) throws Exception {
        //创建发送端接口
        Socket s=new Socket("127.0.0.1",8888);
        //获取输出流,写数据
        OutputStream out =s.getOutputStream();
        byte[]b="你好呀".getBytes();
       out.write(b);
     s.close(); //释放资源
    }
}

服务器端:

public class TCPreceive {
    public static void main(String[] args)  throws  Exception{
        //创建服务器接口,指明自己的端口号
        ServerSocket recive =new ServerSocket(8888);
        Socket socket=recive.accept(); // 阻塞式监听客户端的接入
        InputStream in=socket.getInputStream();  //服务器没有IO流获取客户端对象的IO流

        byte []buffer=new byte[1024];  //这样在用String方式输出会截取汉字产生乱码,最好用字节缓冲输出流
        int len=0;
        while((len=in.read(buffer))!=-1)
        {
            String str=new String(buffer,0,buffer.length);
            System.out.println("收到来自可客户端ip:"+socket.getInetAddress().getHostAddress()+str);
        }
    }
}

注意

服务器是没有IO流的,服务器可以获取到请求的客户端对象socket
使用每个客户端socket中提供的IO流和客户端进行交互
服务器使用客户端的字节输入流读取客户端发送的数据
服务器使用客户端的字节输出流给客户端回写数据

如果是TCP中先启动客户端会报错
而如果是UDP中先启动发送方不会报错,但会正常退出。

1.服务端与客户端的双向回写数据

客户端:

package TCP;

import com.sun.org.apache.bcel.internal.ExceptionConst;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class TCPsend {  //TCP要保证数据被收到所以要先开启服务器
    public static void main(String[] args) throws Exception {
        //创建发送端接口
        Socket s=new Socket("127.0.0.1",8888);
        //获取输出流,写数据
        OutputStream out =s.getOutputStream();

       out.write("你好呀,我是客户端".getBytes());
       //用来提示服务器客户端已经发送数据结束了,不然服务器会一直while循环不知道什么时候结束,导致阻塞
        s.shutdownOutput();
        InputStream in=s.getInputStream();
        int len;
        byte[]b= new byte[1024];
        while((len=in.read(b))!=-1)
        {    String str=new String(b,0,b.length);
        System.out.println(str);
            System.out.println(s.getInetAddress().getHostAddress()+"端口号为:"+s.getPort()+str);
        }
     s.close(); //释放资源
    }
}

服务器端:

package TCP;

import 网络.Server;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPreceive {
    public static void main(String[] args)  throws  Exception{
        //创建服务器接口,指明自己的端口号
        ServerSocket recive =new ServerSocket(8888);
        Socket socket=recive.accept(); // 阻塞式监听客户端的接入

        InputStream in=socket.getInputStream();  //服务器没有IO流获取客户端对象的IO流

        byte []buffer=new byte[1024];  //这样在用String方式输出会截取汉字产生乱码,最好用字节缓冲输出流
        int len=0;
        while((len=in.read(buffer))!=-1)
        {
            String str=new String(buffer,0,buffer.length);
            System.out.println("收到来自客户端ip:"+socket.getInetAddress().getHostAddress()+"端口号为:"+socket.getPort()+str);
        }
       //输出流
        OutputStream out=socket.getOutputStream();
         out.write("服务器已收到数据".getBytes());
         socket.close();

    }
}

服务器端的输出结果:

服务器已收到数据                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
127.0.0.1端口号为:8888服务器已收到数据                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

客户端的输出结果::

收到来自客户端ip:127.0.0.1端口号为:54303你好呀,我是客户端                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

2.从键盘输入数据的包装流案例:

客户端:

package TCP.包装流;

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

public class Client {
    public static void main(String[] args) throws  Exception {
        //创建接收端的接口,指定接收端Ip与端口
       Socket s=new Socket("127.0.0.1",4319);
       //将键盘输入的标准流封装成字符流BufferReader
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        //获取接口的写入流
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

        String str=null;
        while((str=br.readLine())!=null)  //由于是键盘录入数据,不可能得到null所以要设置一个结束标志
        {   if(str.equals("886"))     //设置一个读入流的结束标志
            break;
            bw.write(str);  //将键盘输入的数据写入到服务器
            bw.newLine();
            bw.flush();  //一定要加上缓存,将通道的数据全部写入
        }
        bw.close();
        br.close();//前两个可以不关闭,因为关闭接口也就关闭了读写流接口
       s.close();

    }
}

服务器:

package TCP.包装流;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws  Exception{
        ServerSocket socket;
        //设置服务器端的接口
        socket = new ServerSocket(4319);
        //阻塞式接口
        Socket s=socket.accept();
        //将读入流也封装成字符流,就可以读入一行啦
        BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
        byte[]b=new byte[1024];
        String str=null;
        while((str=br.readLine())!=null) //读入一行字符流
        {
            System.out.println(str);
        }
       s.close();


    }
}
//将键盘数据写入到文件中,封装一个文件写入流
/* BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
        //在服务器中封装一个输出到文件的流,将键盘输入的数据写入到文件中
        BufferedWriter bw= new BufferedWriter(new FileWriter("a.txt"));
        byte[]b=new byte[1024];
        String str=null;
        while((str=br.readLine())!=null) //读入一行字符流
        {
           bw.write(str);
           bw.newLine();
           bw.flush();
        }
       s.close();*/

3.TCP上传一个文本文件

客户端:

package TCP.上传文件;

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

public class Client {
    public static void main(String[] args) throws  Exception {
        //创建接口,并指定接收端的IP和端口
        Socket s=new Socket("127.0.0.1",4329);
        //封装一个文本文件的读入流,表示从文本文件中读取数据
        BufferedReader br=new BufferedReader(new FileReader("副本文件"));
        //封装一个接口输出流,用来向服务器传输数据
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

        //读取文本文件的数据写入到服务器中
        String str=null;
        while((str=br.readLine())!=null)
        {
            bw.write(str);
            bw.newLine();
            bw.flush();
        }
        //同样的要加上一个输出流的关闭提示,不然服务器就不知道你什么时候数据写完,就会一直阻塞
        s.shutdownOutput();

        br.close();//关闭文件即可,不必关闭流包装和接口,否则导致后面无法使用接口流
   //这里封装一个接口的读入流,是用来读取服务器那边的反馈信息
      BufferedReader br2=new BufferedReader(new InputStreamReader(s.getInputStream()));
      String ret=br2.readLine();
      System.out.println(ret);
    }
}

服务器端:

package TCP.上传文件;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws Exception{
        //创建接收接口并指定接收端口
        ServerSocket socket=new ServerSocket(4329);
        //阻塞并返回发送端的接口
        Socket s=socket.accept();
        //封装输入流
        BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
        //封装文本写入流
        BufferedWriter bw =new BufferedWriter(new FileWriter("上传的文件"));
        //将读取到的数据写入文件
        String  str=null;
        while((str=br.readLine())!=null)
        {
            bw.write(str);
            bw.newLine();
            bw.flush();
        }
        bw.close();
        //给客户端一个反馈,封装一个写入流
        BufferedWriter  bw2=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        bw2.write("文件已成功上传".toString());
        bw2.flush();
        bw2.close();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值