Java网络编程总结
网络的两种架构
B/S模型 browser/server 架构指传统的浏览器和服务器的模型,如 www.taobao.com 淘宝网,www.baidu.com 百度网
C/S模型 Client/Server 架构指客户端和服务器的模型,如 QQ , 百度网盘
B/S 主要基于http/https协议,也包含ftp等协议,这些协议基于TCP(传输控制协议,提供可靠的数据传输)
C/S 架构可选的协议就比较多 ,可以是UDP(用户数据报协议)也可以是TCP
关于网络协议具体的的内容,移步
Java 如何实现网络编程
TCP编程
-
客户端实现链接互联网的基本步骤
1.创建Socket类
- 调用Socket(String host,int Port)绑定指定IP地址的服务器的端口
2.向服务器中发送数据
-
socket.getOutputStream()获取输出流
-
通过OutputStream流的write方法向服务器发送信息
-
调用socket.ShutdownOutput()关闭输入流,这样服务器就可以知道什么时候输入结束了,已经关闭的输入流是无法再次打开的
3.从服务器端获取信息
- socket.getInputSream()获取输入流
- 通过read()方法读取信息
4.关闭socket,socket.close()
import jdk.internal.util.xml.impl.Input;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
//TCPClient代码
public class TCPClient {
public static void main(String[] args) throws Exception{
//绑定指定ip和端口的socket
Socket socket =new Socket("127.0.0.1",8080);
//向服务器发送数据
os.write("你好服务器".getBytes(StandardCharsets.UTF_8));
//关闭发送流
socket.shutdownOutput();
//获取服务器的信息
int len=0;
byte[] bytes=new byte[1024];
InputStream is=socket.getInputStream();
len=is.read(bytes);
System.out.println(new String(bytes,0,len));
//关闭
socket.close();
}
}
-
服务器端实现网络编程的基本步骤
1.创建ServerSocket类并绑定特定的端口号监听
2.通过SockeServer.accpet()获取到客户端请求的socket
3.通过socket.socket.getInputSream()获取输入流,通过read()方法读取信息
4.socket.getOutputStream()获取输出流,通过OutputStream流的write方法向客户端发送信息
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
//TCPServer
public class TCPServer {
public static void main(String[] args) throws Exception{
//启动一个ServerSocket监听再8080端口
ServerSocket serverSocket=new ServerSocket(8080);
//循环监听请求
while(true){
//获取一个socket请求
Socket socket=serverSocket.accept();
//启动一个线程用于和socket进行交互
new Thread(new Runnable() {
@Override
public void run() {
try {
//接受客户短的信息
int len=0;
InputStream is = socket.getInputStream();
byte[] buffer =new byte[1024];
while((len=is.read(buffer))!=-1){
System.out.println(new String(buffer,0,len));
}
//向客户端发送信息
OutputStream os= socket.getOutputStream();
os.write("收到".getBytes(StandardCharsets.UTF_8));
//关闭socket
socket.close();
}catch (Exception e){
//打印错误
System.out.println(e);
}
}
}).start();
}
}
}
- 总结,在TCP编程中,Java把客户端和服务器统一抽象为了Socket对象,通过Socket对象的GetIn(out)put获取输入输出流,通过流的read和write方法向对方发送信息,由于服务器端是循环等待客户端的链接,所以服务器端不直接创建socket,而通过ServerSocket方法,获取对应每个请求的socket,进行交互。由于Socket是TCP协议的,一旦建立了TCP通道,服务器端和客户端会默认保持链接,方便接下来的信息进行传送,所以我们需要显示关闭socket(TCP),通过close()方法显示关闭
UDP编程
客户端实现UDP通讯的步骤
-
创建DatagramSocket,即可以绑定端口,也可以不绑定端口(不指定端口会默认绑定一个端口,不会不绑定端口)
-
初始化绑定的信息,包括InetAdress,port,以及要发送的信息
-
利用上一步的信创建一个DatagramPacket
-
利用socket的send方法将刚才包装好的数据报发送出去
-
调用receive接收服务器端发送来的信息,亦可能服务器不发送或者数据报丢失udp是不可靠的传输协议
-
关闭DatagramSocket对象释放资源(让刚刚绑定的端口可以被其他程序接着使用),如果还有其他线程在使用这个Socket那么关闭的时候会发生SocketExpection异常
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.nio.charset.StandardCharsets; //udpclient public class UDPClient { public static void main(String[] args) throws Exception { //获取发送信息的Ip地址,端口号,和发送内容 InetAddress address= InetAddress.getLocalHost(); int port =8080; byte[] bytes="你好这是客户端".getBytes(StandardCharsets.UTF_8); //创建socket对象,和packet对象 DatagramSocket datagramSocket=new DatagramSocket(); DatagramPacket datagramPacket= new DatagramPacket(bytes, bytes.length,address,port); //发送数据 datagramSocket.send(datagramPacket); datagramSocket.receive(datagramPacket); System.out.println(new String(datagramPacket.getData(),0,datagramPacket.getLength())); datagramSocket.close(); } }
服务器端实现UDP通讯步骤
-
创建DatagramSocket绑定在指定的端口,端口号的选项也是可选的,为了能够让客户端连接到服务器,一般都指定端口
-
创建DatagramPacket,并指定一个字节数组,为data,用来接受信息
-
通过DatagramSocket的receive方法接受UDP数据包,并将数据存在DatagramPacket当中
-
调用getAdress获取到这个数据包发送者的IP地址,getPort获取到发送者的端口号
-
重新利用客户端信息并加上想要发送的内容,重新发送
-
关闭DatagramSocket
-
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
//udpserver
public class UDPServer {
public static void main(String[] args)throws Exception {
//创建一个UDPsocket监听在8080端口
DatagramSocket datagramSocket=new DatagramSocket(8080);
//创建DatagramPacket对象用于接受信息
byte[] bytes=new byte[1024];
DatagramPacket datagramPacket=new DatagramPacket(bytes, bytes.length);
datagramSocket.receive(datagramPacket);
//打印接受到信息
System.out.println(new String(bytes,0, bytes.length));
InetAddress inetAddress=datagramPacket.getAddress();
int port = datagramPacket.getPort();
bytes="服务器端收到谢谢".getBytes(StandardCharsets.UTF_8);
datagramPacket.setAddress(inetAddress);
datagramPacket.setPort(port);
datagramPacket.setData(bytes);
datagramSocket.send(datagramPacket);
datagramSocket.close();
}
}
总结,Udp是无连接不可靠的传输协议,他不会针对每个链接对象去进行处理,而针对于数据报进行处理,对于每个数据报,服务获取到相应的信息后,并包装好接下来的信息将通过Packet发送给客户端。通过代码我们可以看到Udp协议的架构应该是一种P2P的架构,通信的双方是对等的,如果已知客户端的信息,并且客户端已经绑定在指定的端口上,那么服务器也可以率先向客户端发送信息。UDP是不可靠的传输信息,没有特定的虚拟通讯链路,服务器端也不会针对每个数据报进行确认,故时常用在一些对通讯要求不高的应用上。但Udp省去了TCP建立三次握手,四次挥手的部分,省去了指定通讯链路,省去了确认信息,以及差错控制信息,所以速度相对来说会快很多。