文章目录
网络编程
网络编程概述
计算机网络
指将地理位置不同的的具有独立功能的多台计算机及其外部设备通过通信线路链接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统
网络编程
用来实现网络互联的不同计算机上运行的相同程序可以进行数据交互
网络模型
计算机网络之间以何种规则进行通信,就是网络模型的研究问题
- OSI开放系统互联模型
- TCP/IP参考模型 传输控制 网络协议
模型图/网络分层
- 物理层:物理设备,这层数据叫比特
- 数据链路层:物理层的数据和MAC(网卡地址)地址的封装和解封,设备为交换机,数据为帧
- 网络层:从下层接收的数据进行封装和解封,设备为路由器 数据叫做(数据)包
- 传输层:定义一些传输协议和端口号,如TCP(传输控制协议,传输率低,可靠性高用于传输大量数据)UDP(用户数据协议 很小 可靠性小)从下层收到的信息再封装和解封,数据叫做段。
- 会话层:通过传输层(端口号:传输端口和接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接收会话请求(设备间需要相互认识,ip也可以是MAC或者主机名)
- 表示层:进行对解析的数据加密和解密,压缩与解压缩。(把计算机能识别的数据转化为人能识别的,二进制)
- 应用层:主要为一些终端应用
网络编程三要素
- ip地址:网络中计算机的唯一标识
- 端口号
- 传输协议
ip地址
A类地址第1字节为网络地址(最高位固定是0),另外3个字节为主机地址。
A类地址范围:1.0.0.0 - 126.255.255.255,其中0和127作为特殊地址。
A类网络默认子网掩码为255.0.0.0,也可写作/8。
A类网络最大主机数量是256×256×256-2=166777214(减去1个主机位为0的网络地址和1个广播地址)
java中ip地址的获取
Class InetAddress(没有public构造方法,方法都是static)
环回地址:127.0.0.1
dos指令:ipconfig
端口-正在运行程序的标识/入口
- 物理端口,网卡号
- 逻辑端口
- 每个网络程序都有逻辑端口
- 标识进程逻辑地址,不同的进程有不同的标识
- 有效:0~65536 0~1024系统和保留端口
协议
通信协议
- UDP将数据源和目的封装成数据包,不需要连接。每一个数据限制64k,因无法链接,属于不可靠协议,不建议传输大数据,速度传输快,可以传输小型数据,或简单信息。
- TCP建立连接,形成数据传输通道,在链接中进行大量数据传输,通过三次握手完成链接。是可靠协议,传输效率低。
- UDP面向无连接协议
- TCP三次握手连接,询问,答复,在传输
- 通常使用混合的协议
- tcp三次握手四次挥手
Socket网络编程
- socket套接字:网络上具有唯一标识的ip地址和端口号组合在一起才能组成的唯一标识
- Socket原理:原理前提
两边都有相同软件的Socket
网络通信的就是两个套接字的通信
套接字之间用IO传输
UDP
UDP:先接受再发送,开发时先写发送在写接收
UDP发送数据实现
package socket;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
/**
* 数据发送方
* 创建发送方socket套接字
* 创建数据,并且打成数据包
* socket发送数据包
* 释放资源
* @author zhang
*
*/
public class MessageSend {
public static void main(String[] args) throws Exception {
byte[] data="zhangrui".getBytes();
send("192.168.43.129",9999,data);
}
public static void send(String ip,int port,byte[] data) throws Exception{
//创建套接字
DatagramSocket socket=new DatagramSocket();
//发送地址
InetAddress address=InetAddress.getByName(ip);
//数据包
DatagramPacket p=new DatagramPacket(data, data.length,address,port);
//发送信息
socket.send(p);
//释放资源
socket.close();
}
}
UDP接受数据实现
package socket;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* UDP协议信息接收方
* 创建接收socket
* 创建数据包
* 调用socket接收方法,将数据填充到数据包
* 解析资源
* 释放资源
* @author zhang
*
*/
public class MessageRec {
public static void main(String[] args) throws Exception {
receive(9999);
}
public static void receive(int port) throws Exception{
//创建接收方socket
DatagramSocket s=new DatagramSocket(port);
//创建接收数据包
byte[] data=new byte[1024];
DatagramPacket p=new DatagramPacket(data,data.length);
//接收数据
s.receive(p);
//解析数据
byte[] d=p.getData();
String str=new String(d,0,p.getLength());
InetAddress address=p.getAddress();
String ip=address.getHostAddress();
System.out.println("正在接收来自"+ip+"的数据。。。");
System.out.println("信息为:"+str);
//释放资源
s.close();
}
}
UDP聊天室
控制台输入的字符必须用GBK编码格式
发送方
package socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* 发送方
*
* @author zhang
*
*/
public class Send {
public static void main(String[] args) throws Exception {
//读取控制台输入
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
//创建套接字
DatagramSocket s=new DatagramSocket();
String line=null;
while((line=br.readLine())!=null){
byte[] data=line.getBytes();
DatagramPacket p=new DatagramPacket(data, data.length,
InetAddress.getByName("192.168.43.129"),9999);
s.send(p);
}
s.close();
}
}
接收方
package socket;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.Arrays;
/**
* 信息接收
*
* @author zhang
*
*/
public class Receive {
public static void main(String[] args) throws Exception {
//创建接收方socket
DatagramSocket s=new DatagramSocket(9999);
//创建接收包
byte[] data=new byte[1024];
DatagramPacket p=new DatagramPacket(data,data.length);
//接收
while(true){
s.receive(p);
//控制台输入必须用GBK字符集接收
String str=new String(p.getData(), 0,p.getLength(), "GBK");
String ip=p.getAddress().getHostAddress();
System.out.println("接收来自"+ip+"的信息"+str);
}
}
}
多线程实现
接收方
package socket;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ThreadReceive implements Runnable{
//创建socket
DatagramSocket s=null;
public ThreadReceive(DatagramSocket s) {
super();
this.s = s;
}
@Override
public void run() {
try {
while(true){
//准备接收数据包
byte[] data=new byte[1024];
DatagramPacket p=new DatagramPacket(data, data.length);
s.receive(p);
//解析数据
String str=new String(p.getData(),0,p.getLength(),"GBK");
String ip=p.getAddress().getHostAddress();
System.out.println("接收到来自"+ip+"的信息:"+str);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
s.close();
}
}
}
发送方
package socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class ThreadSend implements Runnable{
//创建发送Socket
DatagramSocket s=null;
public ThreadSend(DatagramSocket s) {
this.s = s;
}
@Override
public void run() {
try {
//数据
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=br.readLine())!=null){
byte[] data=line.getBytes();
//创建数据包
DatagramPacket p=new DatagramPacket(data, data.length,
InetAddress.getByName("192.168.43.129"),9999);
s.send(p);
if(line.equals("886")){
break;
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
s.close();
}
}
}
主线程
package socket;
import java.net.DatagramSocket;
public class Main {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
ThreadSend send=new ThreadSend(new DatagramSocket());
ThreadReceive receive=new ThreadReceive(new DatagramSocket(9999));
Thread t=new Thread(send);
Thread t1=new Thread(receive);
t.start();
t1.start();
}
}
TCP数据传输代码实现
- socket套接字:socket是客户端,serversocket是服务端的
- tcp的连接依靠的是三次握手,建立链接,回应链接,发送信息 在serversocket完成
- 建立链接,在server完成 通过server的serversocket的accept获得client的socket
客户端
package socket;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* tcp协议下发送端被称为客户端
* 1、建立发送的套接字socket
* 2、建立客户端与服务器端的链接
* 3、建立链接后,通过IO传输数据
* 4、关闭
* 5、双向
* @author zhang
*
*/
public class TCPSend {
public static void main(String[] args) {
Socket s=null;
OutputStream os=null;
try {
//建立套接字
s=new Socket("192.168.43.129",9999);
//获取输出流
os=s.getOutputStream();
//输出数据
os.write("你好啊!".getBytes());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
os.close();
s.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
服务端
package socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* TCP数据接收方,服务器
* @author zhang
*
*/
public class TCPReceive {
public static void main(String[] args) {
//创建套接字
ServerSocket ss=null;
//输入流
InputStream is=null;
//客户端管道
Socket s=null;
try {
ss=new ServerSocket(9999);
//建立链接
s=ss.accept();
is=s.getInputStream();
//解析数据
int len=0;
byte[] data=new byte[1024];
while((len=is.read(data))!=-1){
String str=new String(data,0,len);
System.out.println("信息:"+str);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
is.close();
s.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}