TCP/IP协议: 传输控制协议/因特网互联协议(Transmission Control Protocol/Internet Protocal),是Internet最基本、最广泛的协议。它定义了计算机如何连入因特网,以及数据如何在它们之间传输的标准。它的内部包含一系列的用于处理数据通信的协议,并采用了4层的分层模型(应用层、传输层、网络层和链路层),每一层都呼叫它的下一层所提供的协议来完成自己的需求。
TCP/IP协议中的四层
- 应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。
- 传输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。
- 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。
- 数据链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。
三次握手(建立连接)
- 第一次:客户端向服务端发送请求;
- 第二次:服务端向客户端发送确认请求;
- 第三次:客户端向服务端发送收到确认请求(建立连接完成)
四次挥手(断开连接)
- 客户端向服务端发送断开请求
- 服务端向服务端回复收到
- 服务端向客户端发送断开请求完成
- 客户端回复收到(断开完成)
IP地址:127.0.0.1 IP名:localhost
端口:127.0.0.1:8080
命令行查看端口
查看所有端口:netstat -ano
查看指定端口:netstat -ano|findstr “端口号” ,比如netstat -ano|findstr 8080
查看指定端口的进程:tasklist|findstr “端口号”
杀死指定进程:taskkill /pid 进程号 -f
TCP网络编程
在Java中,提供了两个类用于实现TCP通信程序:
- 客户端:java.net.Socket 类表示。创建Socket对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。
- 服务端:java.net.ServerSocket 类表示。创建ServerSocket对象,相当于开启一个服务,并等待客户端的连接。
构造方法:public Socket(String host, int port)
说明:
服务端开启一个端口,并实时监听客户端发过来的消息。
客户端向指定socket(IP+ 端口号)发送消息。
客户端
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args){
Socket socket = null;
OutputStream os = null;
ByteArrayOutputStream baos=null;
InputStream is=null;
try {
//1、创建Socket对象,它的第一个参数需要的是服务端的IP,第二个参数是服务端的端口
InetAddress inet = InetAddress.getByName("127.0.0.1");
socket = new Socket(inet,8888);
//2、获取一个输出流,用于写出要发送的数据
os = socket.getOutputStream();
//3、写出数据
os.write("你好,我是客户端!".getBytes());
//==========================解析回复==================================
//4、首先必须通知服务器,我已经输出完毕了,不然服务端不知道什么时候输出完毕
//服务端的while循环会一直执行,会阻塞
socket.shutdownOutput();
///5、获取输入流,用于读取服务端回复的数据
is = socket.getInputStream();
baos = new ByteArrayOutputStream();
int len=0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println("收到了来自服务端的消息:"+baos.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {//6、释放资源
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (baos!=null){
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务端
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
OutputStream os=null;
try {
//1、创建服务端的ServerSocket,指明自己的端口号
serverSocket = new ServerSocket(8888);
//2、调用accept接收到来自于客户端的socket
socket = serverSocket.accept();//阻塞式监听,会一直等待客户端接入
//3、获取socket的输入流
is = socket.getInputStream();
//4、读取输入流中的数据
//ByteArrayOutputStream的好处是它可以根据数据的大小自动扩充
baos = new ByteArrayOutputStream();
int len=0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println("收到了来自于客户端"+socket.getInetAddress().getHostName()
+"的消息:"+baos.toString());
//===========================回复==========================================
//5、获取一个输出流,写出回复给客户端
os = socket.getOutputStream();
//6、写出数据
os.write("你好,我是服务端".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {//7、关闭资源
if(serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(baos!=null){
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
UDP网络编程
接收类
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPReceiver implements Runnable{
//创建一个socket
DatagramSocket socket=null;
//接收方自己所在的端口
private int fromPort;
//数据发送者的姓名
private String msgFrom;
public UDPReceiver(int fromPort,String msgFrom) {
this.fromPort = fromPort;
this.msgFrom=msgFrom;
try {
socket=new DatagramSocket(fromPort);//创建一个socket
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while(true){//循环接收
try {
byte[] buffer = new byte[1024 * 8];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet);
String msg = new String(packet.getData(), 0, packet.getLength());
System.out.println(msgFrom+":"+msg);
if (msg.equals("拜拜")){//如果接收到的数据为拜拜,则退出接收
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
//释放资源
socket.close();
}
}
发送类
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UDPSender implements Runnable{
//创建一个socket
DatagramSocket socket=null;
//创建一个流 用于录入键盘的数据
BufferedReader bfr=null;
//发送数据目的地的IP
private String toIP;
//发送数据目的地的端口
private int toPort;
public UDPSender(String toIP, int toPort) {
this.toIP = toIP;
this.toPort = toPort;
try {
socket=new DatagramSocket();//创建一个socket
} catch (SocketException e) {
e.printStackTrace();
}
bfr=new BufferedReader(new InputStreamReader(System.in));//从键盘录入数据到流中
}
@Override
public void run() {
while (true){//循环发送数据
try {
String msg = bfr.readLine();//从流中读取数据
byte[] buffer = msg.getBytes();
InetAddress inet = InetAddress.getByName(toIP);
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length, inet, toPort);
socket.send(packet);
//如果发送了拜拜,则退出发送
if(msg.equals("拜拜")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
//释放资源
if(socket!=null){
socket.close();
}
if (bfr!=null){
try {
bfr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
定义连个交互类
public class BOY {
public static void main(String[] args) {
new Thread(new UDPSender("127.0.0.1",7777)).start();
new Thread(new UDPReceiver(8888,"美女")).start();
}
}
public class GIRL {
public static void main(String[] args) {
new Thread(new UDPSender("127.0.0.1",8888)).start();
new Thread(new UDPReceiver(7777,"帅哥")).start();
}
}
URL
URL(Uniform Resource Locator):统一资源定位符,它表示Internet上某一资源的地址。
通过URL我们可以访问Internet上的各种网络资源,比如最常见的www,ftp站点。浏览器通过解析给定的URL可以在网络上查找相应的文件或其他资源。
URI=URL+URN
- URI:Uniform Resource Identifier ,统一资源标志符。
- URL:Uniform Resource Locator,统一资源定位符。
- URN:Uniform Resource Name,统一资源命名。
格式:
URL的基本结构由5部分组成:
<传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表
例如:http://localhost:8080/index.jsp#a?username=Tom&password=123456