Socket与DatagramSocket的不同方式通信
一、基于TCP协议的Socket客服通信
二、基于UDP协议的DatagramSocket客服通信
由于这两种通信是基于TCP和UDP协议进行的,所有先看一下这两种协议
TCP 和 UDPTCP协议:
- 使用TCP协议前,须先建立TCP连接,形成传输数据通道
- 传输前,采用“三次握手”方式,是可靠的
- TCP协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据报的大小限制在64K内
- 因无需连接,故是不可靠的
- 发送数据结束时无需释放资源,速度快
一、基于TCP协议的Socket客服通信
注意点:
- 通信的两端都要有Socket,是两台机器间通信的端点
- 网络通信其实就是Socket间的通信
- Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输
- 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
1)客户端Socket的工作过程包含以下四个基本的步骤:
- 创建 Socket:根据指定服务端的 IP 地址或端口号构造 Socket 类对象。若服务器端响应,则建立客户端到服务器的通信线路。若连接失败,会出现异常。
- 打开连接到 Socket 的输入/出流: 使用 getInputStream()方法获得输入流,使用 getOutputStream()方法获得输出流,进行数据传输
- 按照一定的协议对 Socket 进行读/写操作:通过输入流读取服务器放入线路的信息(但不能读取自己放入线路的信息),通过输出流将信息写入线程。
- 关闭 Socket:断开客户端到服务器的连接,释放线路
2)服务器程序的工作过程包含以下四个基本的步骤:
- 调用 ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端口上。用于监听客户端的请求。
- 调用 accept():监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字对象。
- 调用 该Socket类对象的 getOutputStream() 和 getInputStream ():获取输出流和输入流,开始网络数据的发送和接收。
- 关闭ServerSocket和Socket对象:客户端访问结束,关闭通信套接字。
代码实现消息互发:
注意:要先测试服务端,让其挂起,然后运行客户端
public class SocketTest {
/*
* Socket
* 客户端 :边读(已存在的原文件)边写(到程序中) 写:是客户端的流socket.getOutputStream();
*/
@Test
public void client() throws Exception, Exception{
/*
* 1、客户端向服务端发送消息
*/
//创建一个客户端
Socket socket = new Socket(InetAddress.getLocalHost(), 25666);
//给服务器发送一句话
OutputStream os = socket.getOutputStream();
os.write("我是客户端发出的消息".getBytes());
//告知服务器输出完了
socket.shutdownOutput();
/*
* 2、客户端接收服务器发送的消息,实现互动的效果
*/
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
System.out.println("客户端:" + br.readLine());
//通知服务器读完了
socket.shutdownInput();
//关流
br.close();
isr.close();
is.close();
os.close();
socket.close();
}
/*
* ServerSocket
* 服务端 :边写(到新的文件中)边读(从程序中) 读:是服务器的流accept.getInputStream();
*/ @Test
public void server() throws Exception{
/*
* 1、服务端接收客户端发送的消息
*/
//创建一个服务端
ServerSocket ss = new ServerSocket(25666);
//接收客户端的请求
Socket accept = ss.accept();
//获取一个输入流,读取客户端发送的数据
InputStream is = accept.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
System.out.println("服务器:" + br.readLine());
accept.shutdownInput();
/*
* 2、向客户端发送数据
*/
//获取一个输出流
OutputStream os = accept.getOutputStream();
os.write("我是服务端发出的消息".getBytes());
accept.shutdownOutput();
//关闭流
br.close();
isr.close();
is.close();
os.close();
accept.close();
ss.close();
}
}- 客户端(发送消息)→服务端 (接收消息)
- 服务端(发送消息)→客户端(接收消息)
这两种情况我都写在同一个方法里面了,但做了很好的区分,这样更容易对比
当然不仅可以发送消息,还可以传输文件(不限文件类型)
/*
* 客户端给服务器发送文件
*/
public class SocketTest2 {
/*
* Socket
* 客户端: 边读(已存在的原文件)边写(到程序中) 写:是客户端的流socket.getOutputStream();
*/
@Test
public void client() throws Exception, Exception{
//创建一个客户端
Socket socket = new Socket(InetAddress.getLocalHost(), 2566);
//给服务器发送一句话
OutputStream os = socket.getOutputStream();
//获取一文件输入流
FileInputStream fis = new FileInputStream(new File("F:/1.jpg"));
byte[] b = new byte[1024];
int len = 0;
while((len = fis.read(b)) != -1){
os.write(b,0,len);
}
socket.shutdownOutput();
//关流
os.close();
socket.close();
fis.close();
}
/*
* ServerSocket
* 服务端: 边写(到新的文件中)边读(从程序中) 读:是服务器的流accept.getInputStream();
*/
@Test
public void server() throws Exception{
//创建一个服务端
ServerSocket ss = new ServerSocket(2566);
//接收客户端的请求
Socket accept = ss.accept();
//获取一个输入流,读取客户端发送的数据
InputStream is = accept.getInputStream();
FileOutputStream fos = new FileOutputStream(new File("F:/2.jpg"));
byte[] b = new byte[1024];
int len = 0;
while((len = is.read(b)) != -1){
fos.write(b, 0, len);
}
accept.shutdownInput();
is.close();
accept.close();
ss.close();
fos.close();
}
}
二、基于UDP协议的DatagramSocket客服通信
注意点:
- 类 DatagramSocket 和 DatagramPacket 实现了基于 UDP 协议网络程序。
- UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
- DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
- UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
public class DatagramSocketTest {
/*
* 客户端
*/
@Test
public void client() throws Exception{
//第一步:创建一个客户端
DatagramSocket socket = new DatagramSocket();
//创建一个数据报/数据包
/*
* DatagramPacket(byte[] buf, int length,
InetAddress address, int port)
length : 应该是buf的长度
*/
String str = "我爱爆米花";
byte[] buf = str.getBytes();
DatagramPacket p = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 3456);
//第二步:发送数据
socket.send(p);
//第三步:关闭服务端
socket.close();
}
/*
* 服务端
*/
@Test
public void server() throws Exception{
//第一步:创建一个服务端
DatagramSocket ds = new DatagramSocket(3456);
byte[] buf = new byte[1024];
DatagramPacket p = new DatagramPacket(buf, buf.length);
//第二步:接收数据,将数据存放到p中
ds.receive(p);
System.out.println(new String(buf, 0, p.getLength()));
//第三步:关闭客户端
ds.close();
}
}不管使用Socket还是DatagramSocket ,客户端都要指定IP(本机为InetAddress.getLocalHost())与端口号
而在接收端,服务端要指定监听的端口。

1051

被折叠的 条评论
为什么被折叠?



