TCP通讯的两个应用程序:服务端和客户端
- 服务器端一般负责监听连接
TCP和UDP的区别
- TCP通讯可靠但效率低(需要连接)
- UDP通讯不可靠但效率高(不需要连接)
socket
- socket是设备通信的端点,socket可以让程序将网络连接当成流,数据通过socket进行io操作
- 个人理解:socket (套间字)是设备通信的端点,socket通过网络连接通道进行i o操作。
(此处应有图)
TCP字节流编程
- 服务端负责监听端口(ServerSocket)并等待连接(ServerSocket.accept)
- 客户端负责连接服务端( new Socket(InetAddress+端口号) )
- 连接成功后通过socket进行io传输
- 注意点
- 端口只能被一个服务端监听
- 服务端可以与多个客户端监听
- 传输完毕后要关闭流
- 输出完数据结束后要设置结束标记
- 代码实现
/**
* 要求:1.编写服务器端与客户端
* 2.服务器端在9999端口监听
* 3、客户端连接到服务器端,发送“hello,server”,并接收服务器端回发的"hello,client"然后退出
* 4.服务器端收到客户端信息,输出,并回发"hello,client",然后退出
*/
- 服务端
public static void main(String[] args) throws IOException {
//思路
//1.监听9999端口
//创建监听
ServerSocket serverSocket = new ServerSocket(4399);
System.out.println("服务器端监听中");
//2.等待连接
Socket socket = serverSocket.accept();
System.out.println("连接成功");
//3.接受客户端信息 输出
//获得输入流
InputStream inputStream = socket.getInputStream();
//显示信息
byte[] b = new byte[1024];
int readlen = 0;
while ((readlen = inputStream.read(b)) != -1){
System.out.println(new String(b,0,readlen));
}
//4.给客户端回发"hello,client"
//获得输出流
OutputStream outputStream = socket.getOutputStream();
//输出
outputStream.write(new String("hello,client").getBytes());
//设置结束标记
socket.shutdownOutput();
//5.关闭流 退出
System.out.println("关闭流 退出噜");
serverSocket.close();
socket.close();
inputStream.close();
outputStream.close();
}
- 客户端
public static void main(String[] args) throws Exception {
//思路
//1.连接服务器端4399
Socket socket = new Socket(InetAddress.getLocalHost(), 4399);
//2.发送hello
//获得输出流
OutputStream outputStream = socket.getOutputStream();
//发送信息
outputStream.write(new String("hello,server").getBytes());
//设置结束标记
socket.shutdownOutput();
//3.接受信息 并输出
//获得输入流
InputStream inputStream = socket.getInputStream();
//显示信息
byte[] b = new byte[1024];
int readlen = 0;
while ((readlen = inputStream.read(b)) != -1){
System.out.println(new String(b,0,readlen));
}
//4.关闭流 退出
socket.close();
outputStream.close();
inputStream.close();
}
TCP字节流编程
- 服务端负责监听端口(ServerSocket)并等待连接(ServerSocket.accept)
- 客户端负责连接服务端( new Socket(InetAddress+端口号) )
- 连接成功后通过socket进行io传输
- 注意点
- 端口只能被一个服务端监听
- 服务端可以与多个客户端监听
- 传输完毕后要关闭流
- 输出完数据结束后要设置结束标记(socket.shutdown()也可以用bufferedWriter.newLine() )
- 如果使用newLine()作为结束标记 对方需要用readline()接收数据
- 代码实现
-
- 服务端
public static void main(String[] args) throws IOException {
//思路
//1.监听9999端口
//创建监听
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务器端监听中");
//2.等待连接
Socket socket = serverSocket.accept();
System.out.println("连接成功");
//3.接受客户端信息 输出
//获得输入流
InputStream inputStream = socket.getInputStream();
//转换成字符流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
//显示信息
String s;
while ((s=bufferedReader.readLine()) != null){
System.out.println(s);
}
//5.关闭流 退出
System.out.println("关闭流 退出噜");
serverSocket.close();
socket.close();
bufferedReader.close();
// outputStream.close();
}
- 客户端
public static void main(String[] args) throws Exception {
//思路
//1.连接服务器端9999
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
//2.发送hello
//获得输出流
OutputStream outputStream = socket.getOutputStream();
//转换成字符输出流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
//输出信息
bufferedWriter.write("hello,小黄");
bufferedWriter.newLine();
bufferedWriter.write("hello,小黄");
//设置结束标记 socket.shutdown()也可以用bufferedWriter.newLine()
//注意! 如果使用newLine()作为结束标记 对面需要用readline()接收数据
bufferedWriter.flush(); // 注意 写完要手动flush()一下
bufferedWriter.newLine();
//4.关闭流 退出
System.out.println("关闭流 退出噜");
bufferedWriter.close();
socket.close();
// inputStream.close();
}
UDP编程
1.基本介绍
- 类DatagramSocket(数据报套间字)与DatagramPacket(数据报)实现了基于UDP协议网络通讯
- DatagramSocket 通过DatagramPacket 发送和接收数据报
- DatagramPacket 对象封装了数据,里面包含了发送方地址和端口号,以及接收方地址和端口号
- 因为DatagramPacket 对象包含了完整的地址信息,所以无须建立发送方与接收方的连接
- 因为无须建立连接,所以UDP没有客户端与服务端的概念,并且是传输不可靠
2.代码实现
/*
1.编写一个接收端,和一个发送端
2.接收端A在9999端口等待接受数据
3.发送端B向接收端A发送数据“hello,明天吃火锅”
4.接收端B接收发送端A发送的数据,回复“好的,明天见“
5.发送端接收回复的数据退出
*/
接收端
public static void main(String[] args) throws IOException {
//1.创建DateGramSocket对象 监听9999端口
DatagramSocket socket = new DatagramSocket(9999);
//2.创建DateGramPacket对象(接收数据)
byte[] b = new byte[1204];
DatagramPacket packet = new DatagramPacket(b, b.length);
//3.等待接收 receive方法会阻塞
socket.receive(packet);
//4.显示数据
//解包
int len = packet.getLength();
byte[] data = packet.getData();
String s = new String(data, 0, len);
System.out.println(s);
byte[] sendData = "好的,明天见".getBytes();
//4.创建DateGramPacket对象 封装数据 "好的,明天见"
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getLocalHost(), 8888);
//发送数据
socket.send(sendPacket);
//7.退出
socket.close();
}
发送端``
public static void main(String[] args) throws IOException {
//1.创建DateGramSocket对象 监听8888端口
DatagramSocket socket = new DatagramSocket(8888);
//2.创建DateGramPacket对象 封装数据 "hello,明天吃火锅"
byte[] sendData = "hello,明天吃火锅".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getLocalHost(), 9999);
//发送数据
socket.send(sendPacket);
//3.创建DateGramPacket对象(接收数据)
byte[] b = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(b, b.length);
//4.等待数据
socket.receive(receivePacket);
//显示数据
int length = receivePacket.getLength();
byte[] receiveData = receivePacket.getData();
String s = new String(receiveData, 0, length);
System.out.println(s);
//5.退出
socket.close();
}
小知识
1. 端口:
客户端与服务器端连接,客户端实际上也是通过某一个端口与服务端进行通讯,这个端口号是由TCP/IP协议分配的,是不确定的,是随机的。
2.netstar
netstat可以让我们看到端口监听状态以及网络连接状态
- 使用方法
打开命令行cmd
- 输入netstat -an (TCP与UDP)
- 内容分析
-
- 协议:TCP与UDP
-
- 本地地址:主机被监听的某一个端口
-
- 外部地址:连接主机端口的某个程序
-
- 状态:主机某个端口的状态 (listening) or (established)