网络通信协议
计算机网络中实现通信必须有一些约定,即通信协议。
TCP 和 UDP
TCP
1)使用TCP协议前,须先建立TCP连接,形成传输数据通道
2)传输前,采用“三次握手”方式,是可靠的
3)TCP协议进行通信的两个应用进程:客户端、服务端
4)在连接中可进行大数据量的传输
5)传输完毕,需释放已建立的连接,效率低
UDP
1)将数据、源、目的封装成数据包,不需要建立连接
2)每个数据报的大小限制在64K内
3)因无需连接,故是不可靠的
4)发送数据结束时无需释放资源,速度快
网络套接字(Socket)
1)网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
2)利用套接字(Socket)开发网络应用程序.
3)通信的两端都要有Socket,是两台机器间通信的端点
4)网络通信其实就是Socket间的通信
5)Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输.也可以说网络编程是IO的扩展,因为在网络传输中也是靠5IO流的操作来完成的。
6)一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
7)启动的时候先启动服务端,在启动客户端
基于Socket的TCP编程
客户端Socket的工作过程包含以下四个基本的步骤:
1)创建 Socket:根据指定服务端的 IP 地址或端口号构造 Socket 类对象。
2)打开连接到 Socket 的输入/出流: 使用 getInputStream()方法获得输入流,使用 getOutputStream()方法获得输出流,进行数据传输
3)按照一定的协议对 Socket 进行读/写操作:
4)关闭 Socket:断开客户端到服务器的连接,释放线路
服务端程序的工作过程包含以下四个基本的步骤:
调用 ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端口上。用于监听客户端的请求。
调用 accept():监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字对象。
调用 该Socket类对象的 getOutputStream() 和 getInputStream ():获取输出流和输入流,开始网络数据的发送和接收。
关闭ServerSocket和Socket对象:客户端访问结束,关闭通信套接字。
客户端给服务端发送数据 (亲测可用)
package com.ghl.demo;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import org.junit.Test;
/**
* 网络编程也叫基于Sokect的编程:分为客户端和服务端
* 客户端发送数据的步骤:
* 第一步:创建一个Socket对象,通过构造器指明对方服务器的ip地址和端口号
* 第二步:通过getOutputStream()方法来发送数据
* 第三步:具体的输出过程write()
* 第四步:关闭相应的流
*/
public class TestTCP {
// 客户端发送数据
@Test
public void testClient() {
Socket socket = null;
OutputStream os = null;
try {
socket = new Socket("127.0.0.1", 8181);// 第一步
os = socket.getOutputStream();// 第二步
os.write("我是客户端,我要给服务端的8181端口发送数据".getBytes());// 第三步
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null && os != null) {
try {
socket.close();
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
// 服务端:接收数据
/**
* 服务端接收数据的步骤:
* 第一步:创建一个ServerSocket对象,通过构造器指明自身的对象(在服务端是ServerSocket)
* 第二步:调用accept()的方法,返回一个Socket对象
* 第三步:调用Socket对象的getInputStream()获取一个从客户端接收过来的数据
* 第四步:对获取的输入流进行操作
* 第五步:关闭相应的流
*/
@Test
public void testServer() {
ServerSocket server = null;
Socket socket =null;
InputStream is =null;
try {
server = new ServerSocket(8181);
socket = server.accept();
is = socket.getInputStream();
byte[] b=new byte[1024];
int len;
while((len=is.read(b))!=-1) {
String str=new String(b, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(server!=null) {
try {
server.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(socket!=null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(is!=null) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
客户端给服务端发送数据,服务端给客户但一个响应,(亲测可用)
package com.ghl.demo;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.junit.Test;
/**
* 实现功能:客户端给服务端发送数据,服务端告诉客户端我已收到你发的信息
*
*/
public class TestTCP1 {
// 客户端发送数据
@Test
public void testClient() {
Socket socket = null;
OutputStream os = null;
InputStream is=null;
try {
//1.客户端先给服务端发送数据
socket = new Socket("127.0.0.1", 8181);// 第一步
os = socket.getOutputStream();// 第二步
os.write("我是客户端,我要给服务端的8181端口发送数据".getBytes());// 第三步
//2.客户端告诉服务端我的数据已发送完毕
socket.shutdownOutput();
is= socket.getInputStream();
byte[] b=new byte[1024];
int len;
while((len=is.read(b))!=-1) {
String str=new String(b, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null && os != null) {
try {
socket.close();
os.close();
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
// 服务端:接收数据
@Test
public void testServer() {
ServerSocket server = null;
Socket socket =null;
InputStream is =null;
OutputStream os = null;
try {
server = new ServerSocket(8181);
socket = server.accept();
is = socket.getInputStream();
byte[] b=new byte[1024];
int len;
while((len=is.read(b))!=-1) {
String str=new String(b, 0, len);
System.out.println(str);
}
os=socket.getOutputStream();
os.write("我是服务端,我已接收到客户端发送的数据".getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally {
if(server!=null) {
try {
server.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(socket!=null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(os!=null) {
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(is!=null) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
客户端发一个文件(图片)给服务端,服务端接收存在本地,并返回接收成功给客户端(亲测可用)
package com.ghl.demo;
import static org.hamcrest.CoreMatchers.instanceOf;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.junit.Test;
/**
* 客户端发一个文件(图片)给服务端,服务端接收存在本地,并返回接收成功给客户端
*
*/
public class TestTCP2 {
@Test
public void testClient() {
Socket socket = null;
OutputStream os = null;
InputStream is = null;
FileInputStream fis=null;
try {
// 1.客户端先给服务端发送数据
socket = new Socket("127.0.0.1", 8181);
os = socket.getOutputStream();
fis = new FileInputStream(new File("1.jpg"));
byte[] b1 = new byte[1024];
int len1;
while ((len1 = fis.read(b1)) != -1) {
os.write(b1, 0, len1);
}
// 2.客户端告诉服务端我的数据已发送完毕
socket.shutdownOutput();
is = socket.getInputStream();
byte[] b = new byte[1024];
int len;
while ((len = is.read(b)) != -1) {
String str = new String(b, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null && os != null) {
try {
socket.close();
os.close();
is.close();
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
// 服务端:接收数据
@Test
public void testServer() {
ServerSocket server = null;
Socket socket = null;
InputStream is = null;
OutputStream os = null;
FileOutputStream fos = null;
try {
server = new ServerSocket(8181);
socket = server.accept();
is = socket.getInputStream();
fos = new FileOutputStream(new File("2.jpg"));
byte[] b = new byte[1024];
int len;
while ((len = is.read(b)) != -1) {
fos.write(b, 0, len);
}
os = socket.getOutputStream();
os.write("我已接收到你发送的数据".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (server != null) {
try {
server.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
UDP网络通信
1)类 DatagramSocket 和 DatagramPacket 实现了基于 UDP 协议网络程序
2)UDP数据报通过数据报套接字 DatagramSocket 发送和接收
3)DatagramPacket 对象封装了UDP数据报,
4)UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
通信 流 程:
1)DatagramSocket与DatagramPacket
2)建立发送端,接收端
3)建立数据包
4)调用Socket的发送、接收方法
5)关闭Socket
package com.ghl.demo;
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 org.junit.Test;
/**
* UDP如和以数据报的形式发送数据
*/
public class TestUDP {
//发送端
@Test
public void send() {
DatagramSocket datagramSocket=null;
try {
datagramSocket = new DatagramSocket();
byte[] buf="我是发送端".getBytes();
//创建一个数据报,每一个数据报不能大于64k发送ip和端口号,以及要发送的数据
DatagramPacket pack=new DatagramPacket(buf, 0, buf.length,InetAddress.getByName("127.0.0.1"),8090);
datagramSocket.send(pack);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
datagramSocket.close();
}
//接收端
@Test
public void recive() {
DatagramSocket ds=null;
DatagramPacket dp=null;
try {
ds = new DatagramSocket(8090);
byte[] b=new byte[1024];
dp = new DatagramPacket(b, 0, b.length);
ds.receive(dp);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String str=new String(dp.getData(),0,dp.getLength());
System.out.println(str);
ds.close();
}
}