二十三、Java基础--------网络编程

时间:2021-08-17 09:11:07

Java中另一个重要技术就是网络编程了,为了更好的学习web方向的知识,有必要对java之网络编程好好学习,本文将围绕网络编程技术进行分析。

常见的网络协议:UDP、TCP

UDP

1、 将数据源和目的封装为数据包,不需要建立连接

2、每个数据包大小在64K内

3、因为面向无连接,所以不可靠(丢失数据)

4、不需要连接,速度快

常见的UDP:聊天、视频会议、桌面共享等等

TCP

1、 建立连接,形成传输数据的通道

2、在连接中进行大量数据的传输

3、通过三次握手完成连接,是可靠协议

4、必须建立连接,效率会相对较低

Socket

Socket就是为网络服务的一种机制,通信两段都有socket,网络通信其实就是socket间的通信。数据自练个socket间通过IO传输。

UDP建立连接步骤

需求:通过UDP传输方式,将一段文字发送出去,另一端进行接受并打印

思路:

发送端:

1、建立UDP socket服务

2、提供数据,将数据封装到数据包中

3、通过socket服务,将数据包发送出去

4、关闭资源

接受端:

1、定义UDP socket服务,通常会监听一个端口,方便与明确该应用程序处理的对象。

2、定义一个数据包,以便于存储接收到数据,数据包对象中提供了更多操作接收数据处理的方法

3、通过socket服务的receive方法,将接收到的数据包存于已定义的数据包中。

4、通过数据对象特有的功能将这些不同的数据取出,并进行后续的处理

5、关闭资源

具体步骤:

发送端:

1、创建UDP服务,通过DatagramSocket对象

DatagramSocket ds =new DatagramSocket();

2、确定数据并封装成数据包

DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAdress,port)

3、通过socket服务,将已经封包的数据进行发送

ds.senf(dp)

4、关闭资源

ds.close();

接收端:

1、创建UDP socket,建立端点(指明监听的端口)

DatagramSocket ds =new DatagramSocket(100010);

2、 定义数据包用于存储接受进来的数据

Byte []by=new byte[1024];

DatagramPacket dp=new DatagramPacket(by,by.length);

3、通过服务的receive方法接受数据,并存于到已定义的数据包中

ds.receive(dp);

4、通过数据包的特有方法去除取出其中的数据

String s=new String(dp.getData());

5、关闭资源

ds.close();

TCP建立连接步骤

需求:建立TCP链接,并传输一段数据到服务器,服务器接收数据并打印该数据

客户端

1、 建立服务端点,指明主机名以及端口号

Socket s=new Socket("127.0.0.1",10010);

2、读取客户端要传送的数据

byte []by="TCP I am coming".getBytes();

3、通过socket输出流将数据发给服务器

OutputStream out=s.getOutputStream();

out.wirte(by);

5、关闭资源

s.close();

服务端:

1、 建立服务端并指明监听端口

ServerSocket ss=new ServerSocker=t(10010);

2、开启服务,并接受数据

Scoket s=ss.accept();

3、读取接受到的数据,并封装成包(本例只是打印)

InputStream in=s.getInputStream();

int len=0;

byte by[]=new byte[1024];

len=in.read(by);

System.out.println(new String(by,0,len));

4、关闭资源

s.close();

案例分析:

    需求:编写一个UDP聊天程序:
            分析:

有接受数据的部分,和发数据的部分,这两部分需要同时执行,这就需要用到多线程了

发送端:

/*
* 编写一个聊天程序:
* 分析:
* 有接受数据的部分,和发数据的部分,这两部分需要同时执行,这就需要用到多线程了
* */
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;
/*
* 发送端
*
* */
public class UDP_Send_03 implements Runnable{
private DatagramSocket ds;
UDP_Send_03(DatagramSocket ds){
this.ds=ds;
}
public void run() {
try {
ds=new DatagramSocket();
Scanner sc=new Scanner(System.in);
String line;
while((line=sc.nextLine())!=null){
if("886".equals(line))
break;
byte by[]=line.getBytes();
DatagramPacket dp=new DatagramPacket(by,by.length,InetAddress.getByName("127.0.0.1"),10110);
ds.send(dp);
}
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} }

接收端:

import java.io.IOException;
import java.net.*; /*
* 编写一个聊天程序:
*
* 接受端
* */
public class UDP_Rec_03 implements Runnable {
private DatagramSocket ds;
UDP_Rec_03(DatagramSocket ds){
this.ds=ds;
}
public void run() {
try {
ds=new DatagramSocket(10110); while(true){
byte by[]=new byte[1024]; DatagramPacket dp=new DatagramPacket(by,by.length);
ds.receive(dp);
String data=new String(dp.getData(),0,dp.getLength()); System.out.println(data);
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} }
//通过多线程的方式同时开启两个服务,这样就可以模拟聊天软件的环境进行交流了
public static void main(String[] args) throws SocketException {
DatagramSocket ds=new DatagramSocket();
UDP_Rec_03 rec=new UDP_Rec_03(ds);
UDP_Send_03 send=new UDP_Send_03(ds);
new Thread(rec).start();
new Thread(send).start(); }
}

案例2:编写一个基于TCP的程序,完成客户端向服务器发送一段文字,服务器接收到后返回一段文字,客户端打印反馈的信息

客户端:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException; /*
* 文件复制,需求:将客户端的文件发到服务端,进行磁盘存储
* */
public class CopyOfTCP_cli_04优化版 {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s=new Socket("127.0.0.1",10011);
//获取输出流,将字节转化为字符,可以一次写一行数据
PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
//读取文件,用到了带缓冲的Reader,可以一次读取一行
BufferedReader br=new BufferedReader(new FileReader("E:\\a.txt"));
String line=null;
while((line=br.readLine())!=null){
pw.println(line);
}
//文件发送完成,需要发送一个结束标记 要格外注意
pw.println("over"); //或者使用s.shutdownOutput(); BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); while((line=in.readLine())!=null)
{
System.out.println("服务器说:"+line);
}
br.close();
in.close();
pw.close();
s.close(); }
}

服务端:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket; public class CopyOfTCP_ser_04优化版 {
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(10011); Socket s=ss.accept();
//接受客户端发送的文件,用到了缓冲,并且将字节流转化为了字符流
BufferedReader br =new BufferedReader(new InputStreamReader(s.getInputStream()));
//向文件中写数据,用到了缓冲,可以写一行
BufferedWriter bo=new BufferedWriter(new FileWriter("E:\\BB.txt"));
//向客户端写数据,用到了将字节流包装为Printwriter 从而可以将字节转化为字符串处理
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
String line=null;
while((line=br.readLine())!=null){
if("over".equals(line))
break;
bo.write(line);
bo.newLine();
bo.flush();
}
out.println("文件收到");
out.flush();
s.close(); }
}