1.何为网络编程
通过计算机连接起来,在同一个网络中遵守同样的规则,可以进行互相的通信。
网络通信协议:常见的TCP/IP协议,还有其它协议。
传数据,必须发送的和收到的数据是一样的。
2.通信两要素
ip+端口号
注:ip可以理解为收货地址,端口号可以理解为门牌号。
3.通信模型
4.TCP/IP协议
InetAddress
方法
getByName(String host) 确定主机名称的IP地址
isReachable(int timeout) 测试该地址是否可达。
public class InetAddressDemo {
public static void main(String[] args) throws IOException {
InetAddress localHost=InetAddress.getLocalHost();
System.out.println("本机host:"+localHost);
InetAddress inetAddress=InetAddress.getByName("www.jd.com");
//这个对象是由域名和ip地址组成的,用/连接起来
//ip:www.jd.com/119.147.159.135
System.out.println("ip:"+inetAddress);
String[] spilt=inetAddress.toString().split("/");
for (String s : spilt) {
System.out.println(s);
}
System.out.println("************");
System.out.println("域名:"+spilt[0]);
System.out.println("ip地址:"+spilt[1]);
//ping命令 ping的是当前机器和要访问的ip是否能连通
boolean reachable=inetAddress.isReachable(60);
System.out.println("是否可达:"+reachable);
//获取本机地址
InetAddress localHost2=InetAddress.getLocalHost();
System.out.println("loaclHost:"+localHost2);
}
}
TCP编程
TCP是可靠的传输协议,IP是网络互联协议。
要连接另外一台计算机进行可靠的传输,必须要三次握手
三次握手
每次要传输前,都要三次握手,但并不是每次都很顺利,只不过没有连接成功,它一直在干这事而已。
四次挥手
第一次:
主动方:我要断开连接(FIN)
第二次:
被动方:好的,知道了,但我还有些数据要发(ACK),等我发完
第三次:
被动方:我的数据已经发完了(FIN+ACK)
第四次:
主动方:确认没有了吗?(ACK),没有我就关了哦。
被动方:看来他要关了。
现在的上传下载,也不管是图片,影像,还是音频等都是使用TCP/IP协议,因为更加可靠。可靠的会有缺点,性能会差一些。
ServerSocket:服务端套接字
构造器: ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
方法:
accept() 侦听要连接到此套接字并接受它
服务端
public class TCPServer {
public static void main(String[] args) throws IOException {
System.out.println("TCPServer已启动...");
//1.创建服务端套接字,监听端口
ServerSocket ss=new ServerSocket(6666);
//2.通过调用accept方法获得客户端的套接字,Socket
Socket socket=ss.accept();
//3.获取客户端socket的输入流对象,用来获取客户端传送的信息
InputStream is=socket.getInputStream();
//创建缓冲数组
byte[] b=new byte[1024];
int hasRead=0;
//循环读到的内容
while ((hasRead=is.read(b))>0) {
System.out.println("接受到客户端发来的信息:"+new String(b,0,hasRead));
}
//4.关闭Socket和ServerSocket 从小到大关闭
is.close();
socket.close();
ss.close();
}
}
Socket 客户端套接字
方法:
getInputStream:获得输入 流
getOutputStream:获得输出流
客户端
public class TCPClient {
public static void main(String[] args) throws IOException {
System.out.println("TCPClient已启动......");
//1.创建客户端套接字,需要传入两个参数IP,端口
Socket s=new Socket(InetAddress.getByName("127.0.0.1"),6666);
//2.获得套接字输出流对象
OutputStream out=s.getOutputStream();
//写到服务器的信息内容
String line="hello,我是客户端..";
//写
out.write(line.getBytes());
//3.关闭客户端套接字对象
out.close();
s.close();
}
}
改良版的tcp例子
服务端
public class TCPServer2 {
public static void main(String[] args) throws IOException {
System.out.println("TCPServer2正在运行中..");
ServerSocket ss = new ServerSocket(6666);
Socket socket=null;
InputStream is=null;
try {
while (true) {
//1.创建服务端套接字,监听端口
//ServerSocket ss=new ServerSocket(6666);
//2.通过调用accept方法获得客户端的套接字,Socket
socket=ss.accept();
//3.获取客户端socket的输入流对象,用来获取客户端传送的信息
is=socket.getInputStream();
//创建缓冲数组
byte[] b=new byte[1024];
int hasRead=0;
//循环读到的内容
while ((hasRead=is.read(b))>0) {
System.out.println("接收到TCPClient2发来的信息:"+new String(b,0,hasRead));
if (new String(b,0,hasRead).equalsIgnoreCase("bye")) {
break;
}
}
break;
}
}catch (Exception e) {
e.printStackTrace();
}finally {
//4.关闭Socket和ServerSocket
is.close();
socket.close();
ss.close();
System.out.println("TCPServer2已关闭...");
}
}
}
客户端
public class TCPClient2 {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("TCPClient2正在运行中..");
Scanner sc=new Scanner(System.in);
Socket s=new Socket(InetAddress.getByName("127.0.0.1"),6666);;
OutputStream out=null;
try {
while (true) {
//1.创建客户端套接字,需要传入两个参数IP,端口
// s=new Socket(InetAddress.getByName("127.0.0.1"),6666);
//2.获得套接字输出流对象
out=s.getOutputStream();
System.out.println("请输入内容(单独输入bye,按下回车,结束输入):");
//写到服务器的信息内容
String line=sc.nextLine();
//写
out.write(line.getBytes());
if (line.equalsIgnoreCase("bye")) {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("输入结束..");
//3.关闭客户端套接字对象
out.close();
s.close();
//关闭输入流对象
sc.close();
}
}
}
5.UDP协议
特点:UDP是无连接通信协议,适用于传送少量数据,对可靠性要求的应用场景。
在传输时,数据的发送和接收不建立连接。发送的这方不管接收方是否接收到。
生活中场景:微信的视频、语音通话就不是可靠传输,有时会丢失语音,或视频信息。
不可靠,传输量少,只管发,不管收
DataGramSocket:构造器有端口是服务器,没端口是客户端
receive(DatagramPacket p) 从此套接字接收数据报包。
void send(DatagramPacket p) 从此套接字发送数据报包。
DataGramPacket
做这个测试前,服务端先打开 !
服务端
public class UDPServer {
public static void main(String[] args) throws IOException {
System.out.println("服务端已开启.....");
//1.创建服务端的DatagramSocket,这里的构造器需要端口8888,这是约定好的
DatagramSocket ds=new DatagramSocket(8888);+
//缓冲数据
byte[] b=new byte[1024];
//2.创建数据报包对象
DatagramPacket dp=new DatagramPacket(b, b.length);
// 3.调用receive方法接收信息
//receive接收客户端是数据报包,填充dp
ds.receive(dp);
//4.数据在dp数据报包里面
String str=new String(b,0,dp.getLength());
System.out.println("接收到客户端的消息:"+str);
//关闭服务端
ds.close();
}
}
客户端
public class UDPClient {
public static void main(String[] args) throws IOException {
try (//1.创建DatagramSocket对象,客户端对象
DatagramSocket ds = new DatagramSocket()) {
//2.准备消息
String line="hello,我是客户端";
//这里的line.getBytes().length是防止服务端接收不全
//3.创建数据报包对象DatagramPacket
DatagramPacket dp=new DatagramPacket(line.getBytes(), line.getBytes().length,
InetAddress.getByName("169.254.140.109"),8888);
//169.254.140.109是UDPServer的ip地址,这里是本机ip地址
//调用send发送
ds.send(dp);
//关闭
ds.close();
}
System.out.println("客户端成功发送消息....");
}
}
改良版的udp例子
把服务器改为可以不间断的接收客户端的消息,循环
客户端改成可以通过控制台输入信息
服务端
public class UDPServer2 {
public static void main(String[] args) throws IOException {
System.out.println("UDPServer2已开启...");
//创建文件实例
File f=new File("D:\\test2\\niu.txt");
while (true) {
//创建服务端套接字
DatagramSocket ds=new DatagramSocket(8888);
//创建一个字节缓冲数组
byte[] b=new byte[1024];
//创建数据报包
DatagramPacket dp=new DatagramPacket(b, b.length);
//套接字调用receive方法
ds.receive(dp);
// System.out.println("dp:"+dp);
// System.out.println("***********");
//拼接字符串 数据在dp数据报包里面
String line=new String(b,0,dp.getLength());
System.out.println("接收到客户端的信息:"+line);
//写道记事本 true:可追加内容,就不用每次覆盖原文
try(Writer w=new FileWriter(f,true)) {
//\r\n是相当按了回车
w.write(line+"\r\n");
} catch (Exception e) {
e.printStackTrace();
}
//提示信息
System.out.println("客户端发送的信息,服务端已收到,已写入文件:"+f+"中");
ds.close();
}
}
}
客户端
public class UDPClient2 {
public static void main(String[] args) throws IOException {
System.out.println("UDPClient2运行中...");
Scanner sc=new Scanner(System.in);
while (true) {
//创建客户端套接字
DatagramSocket ds=new DatagramSocket();
System.out.println("请输入内容(单独输入bye,按下回车,结束输入):");
String line=sc.nextLine();
//判断
if (line.equalsIgnoreCase("bye")) {
System.out.println("结束输入...");
break;
}
//创建数据报包对象
DatagramPacket dp=new DatagramPacket(line.getBytes(), line.getBytes().length,
InetAddress.getByName("127.0.0.1"),8888);
//发送消息到服务器
ds.send(dp);
//关闭
ds.close();
}
System.out.println("客户端已成功发送信息到服务端...");
sc.close();
}
}