基本概念
网络通信协议
通信协议的分层:
名义上标准:ISO标准参考模型
应用层---表示层---会话层---传输层---网络层---数据链路层---物理层
事实标准:TCP/IP协议栈
应用层(Telnet ,FTP,SFTP,SMTP,DNS,HTTP)-----------------传输层(TCP/UDP)---网路层(IP)--物理+数据链路层
数据封装和拆封(发送数据,接收数据)
TCP协议和UDP协议
TCP:三次握手
UDP:一种无连接传输协议提供面向事务的简单不可靠信息传送服务
IP地址和端口号
IP地址:用来标志网络中的一个通信实体的地址,通信实体可以是计算机,路由器
public static void main(String[] args) throws IOException {
//获取本地主机的信息
InetAddress host = InetAddress.getLocalHost();
System.out.println(host);
System.out.println("主机名:"+host.getHostName());
System.out.println("iP地址:"+host.getHostAddress());
//通过主机名/ip地址获取主机信息
//可以是主机名,网址,ip地址
InetAddress name = InetAddress.getByName("www.baidu.com");
System.out.println(name);
}
端口
端口号分类:
公认端口号: 0-1023 比如80端口分配给www,21端口分配给FTP
注册端口:1024-49151分配给用户进程或应用程序
动态/私有端口49152-65535
public static void main(String[] args) {
InetSocketAddress address = new InetSocketAddress("www.baidu.com", 12345);
System.out.println(address);
System.out.println("ip地址"+address.getAddress().getHostAddress());
System.out.println("域名+端口"+address.getAddress());
System.out.println("端口"+address.getPort());
System.out.println("域名"+address.getHostName());
}
URL
统一资源定位符:协议+存放资源的主机名,端口号和资源文件名
public static void main(String[] args) throws IOException {
URL url = new URL("http://www,baidu.com/DRP?username=admin,password=123456");
System.out.println(url.toString());
System.out.println("协议"+url.getProtocol());
System.out.println("端口"+url.getPort());
System.out.println("路径"+url.getPath());
System.out.println("主机名"+url.getHost());
System.out.println("传递数据"+url.getQuery());
System.out.println("端口后数据"+url.getFile());
}
套接字Socket
socket就是应用层和传输层之间的桥梁
TCP编程
TCP通信原理
服务器创建ServerSocket,在指定端口监听并处理请求
客户端口创建Socket,向服务器发送请求
单向
/**
* 登陆服务器端
* 1.单向:接收客户端发送的数据并打印输出
* @author lenovo
*
*/
public class LoginServer {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象,指定当前使用的端口号是什么?
ServerSocket server = new ServerSocket(8888);
//接收客户端Socket对象连接建立,等待客户端的连接
Socket socket = server.accept();
InetAddress addr = socket.getInetAddress();
System.out.println("客户端连接成功ip地址"+addr.getHostAddress()+",端口号"+socket.getPort());
//接收客户端发送信息
//获取输入流用于接收信息
InputStream is = socket.getInputStream();
//利用数据流包装输入流
DataInputStream dis = new DataInputStream(is);
//通过流来接收数据
String msg = dis.readUTF();
//打印输出
System.out.println(msg);
//关闭资源
server.close();
}
}
```java
/*
* 登陆客户端
* 连接服务器发送一句话
*/
public class LoginClient {
public static void main(String[] args) throws IOException {
//创建socket对象,指定连接哪个服务器,还需要服务端应用程序的端口号
Socket client =new Socket("127.0.0.1", 8888);
//准备消息并发送
//获取 输出流并转换为数据流
OutputStream os = client.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("你好,服务器");
//关闭资源
client.close();
}
实现用户登录的功能
user.java
public class User implements Serializable{
private static final long serialVersionUID = 1L;
private String username;
private String password;
public User() {
super();
}
public User(String username, String password) {
super();
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
客户端
/*
* 登陆客户端
* 连接服务器发送一句话
*/
public class LoginClient {
public static void main(String[] args) throws IOException {
//创建socket对象,指定连接哪个服务器,还需要服务端应用程序的端口号
Socket client =new Socket("127.0.0.1", 8888);
//创建扫描器接收用户的输入
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String username = sc.nextLine();
System.out.println("请输入密码");
String password = sc.nextLine();
//封装user对象
User user = new User(username, password);
//准备消息并发送
//获取 输出流并转换为对象流
OutputStream os = client.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(user);
//接收服务端的返回信息
DataInputStream dis=new DataInputStream(client.getInputStream());
System.out.println(dis.readUTF());
sc.close();
//关闭资源
client.close();
}
}
服务端
public class LoginServer {
public static void main(String[] args) throws IOException{
//创建ServerSocket对象,指定当前使用的端口号是什么?
ServerSocket server = new ServerSocket(8888);
//统计客户端的个数
int count=0;
while(true){
//接收客户端Socket对象连接建立,等待客户端的连接
Socket socket = server.accept();
count++;
System.out.println("当前客户端数量"+count);
//创建线程并行
SocketThread thread = new SocketThread(socket);
thread.start();
}
//关闭资源
//server.close();
}
}
线程创建
public class SocketThread extends Thread{
private Socket socket;
/**
* @param socket
*/
public SocketThread(Socket socket) {
super();
this.socket = socket;
}
@Override
public void run() {
//输出客户端消息
System.out.println("客户端连接成功ip地址"+socket.getInetAddress().getHostAddress()+",端口号"+socket.getPort());
//接收用户发送的user对象
try {
//准备对象流,接收user对象
ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
//通过输出数据流进行反馈
DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
User user = (User) ois.readObject();
if(user.getUsername().equals("admin")&&user.getPassword().equals("123456")){
dos.writeUTF("登陆成功");
}else{
dos.writeUTF("登陆失败");
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally{
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
UDP编程
实现在线客服的功能
/*
* udp发送端
*/
public class Udpsend {
public static void main(String[] args) throws IOException {
//创建DatagramSocket
DatagramSocket socket=new DatagramSocket(7777);
Scanner sc = new Scanner(System.in);
String msg="";
while(!(msg=sc.nextLine()).equals("over")){
byte[] buf =msg.getBytes();
//准备数据包
DatagramPacket packet=new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.0.255"), 6666);
//发送数据包
socket.send(packet);
}
sc.close();
//关闭资源
socket.close();
}
}
/*
* 接收端
*/
public class UdpReceive {
public static void main(String[] args) throws IOException {
//创建DatagramSocket
DatagramSocket socket=new DatagramSocket(6666);
byte[] buf=new byte[1024];
//准备数据包
DatagramPacket packet=new DatagramPacket(buf, buf.length);
while(true){
//接收数据包
socket.receive(packet);
//打印接收到的信息
byte[] data = packet.getData();
String msg=new String(data,0,packet.getLength());
System.out.println(packet.getAddress().getHostName()+":"+msg);
}
}
}