网络编程
网络编程
1 网络编程的三个要素
1.1 、IP地址或主机名
-
InetAddress
-
String:192.168.24.71
- 每一个整数是1~255
-
域名:www.baidu.com
- 通过域名解析器,找对对应的ip地址
1.2 、端口号
-
0~65535
-
建议不要使用
-
0~1023
- 用于基础服务
-
tomcat/jboss
- 8080
-
mysql
- 3306
-
oracle
- 1521
-
sql server
- 1433
-
浏览器:http
- 80
-
….
-
1.3 、网络协议
-
OSI理想参考模型
-
TCP/IP的四层实现模式
-
传输层
-
TCP
- 面向连接的,可靠的,适用于大数据传输,速率相对低,在传输之前会先“三次握手”,在断开之前会“四次挥手”
-
UDP
- 非面向连接的,不可靠的,适用于数据比较小的,<=64kb,相对速率高
-
-
应用层
- http/https
- ftp
2 网络编程的API
2.1 Socket
-
套接字
- 表示通信的两个端点,两边各一个
-
分类
-
流套接字
-
用于TCP的通信
-
ServerSocket
- 转门用于服务器用来监听和接收客户端的连接
-
Socket
- 用于服务器和客户端的通信
-
-
-
数据报套接字
-
用于UDP的通信
-
DatagramSocket
- 用于UDP的两端的通信
-
-
-
2.2 TCP编程步骤
-
服务器
-
1、先创建ServerSocket
-
ServerSocket server = new ServerSocket(端口号);
- 指定端口号进行监听,客户端通过这个端口号与它进行连接和通信
-
-
2、接收客户端的连接
-
Socket socket = server.accept();
- 每一个客户端就要有自己的一个Socket
- 如果希望不同的客户端通信“同时”进行,需要每一个socket用一个线程进行维护
-
-
3、通过socket进行收或发消息
-
收消息
-
InputStream is = socket.getInputStream();
- 可以在此基础上,包装缓冲流,转换流,对象流,打印流,数据流等
-
-
发消息
-
OutputStream out = socket.getOutputStream();
- 可以在此基础上,包装缓冲流,转换流,对象流,打印流,数据流等
-
-
-
4、与客户端断开连接
- socket.close();
-
-
客户端
-
1、先与服务器建立连接,通过创建一个Socket,要指定服务器的IP和端口号
- Socket socket = new Socket(服务器的IP,服务器的监听端口号);
-
2、通过socket进行收或发消息
-
收消息
-
InputStream is = socket.getInputStream();
- 可以在此基础上,包装缓冲流,转换流,对象流,打印流,数据流等
-
-
发消息
-
OutputStream out = socket.getOutputStream();
- 可以在此基础上,包装缓冲流,转换流,对象流,打印流,数据流等
-
-
收和发可以用不同的线程进行维护
-
-
3、与客户端断开连接
- socket.close();
-
-
示例一
package com.atguigu.tcp1;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.junit.Test;
/*
-
TCP:面向连接
-
通信的两端分角色:服务器端和客户端
-
-
服务器端等着被连接,客户端主动连接
-
服务器端:
-
1、ServerSocket:用来接收客户端的连接信息
-
2、Socket:用来与某个客户端进行通信
-
客户端:
-
1、Socket:用来与服务器进行通信
*/
public class TestTCP1 {
@Test
public void server()throws Exception{
//1、创建ServerSocket,看成:开启服务器 ,需要指定一个端口号,监听是否有客户端来连接
ServerSocket ss = new ServerSocket(9090);
while(true){
System.out.println("等待您的链接....");
//2、等待客户端的连接,接收客户端的连接(如果没有人连接,那么这句代码会阻塞)
//一旦有客户端连接成功,那么就会产生一个Socket对象,专门负责和这个客户端通信
Socket socket = ss.accept();
System.out.println(socket.getInetAddress().getHostAddress()+"连接成功");
//3、可以接收消息,或发生消息
//例如:先发:“欢迎登陆”
//在接收消息
//发消息:输出流,OutputStream
OutputStream output = socket.getOutputStream();
output.write("欢迎登陆".getBytes());
socket.shutdownOutput();
//收消息
InputStream is = socket.getInputStream();
byte[] data = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while((len= is.read(data)) !=-1){
sb.append(new String(data,0,len));
}
System.out.println("服务器收到的消息:" + sb);
//4、关闭连接
socket.close();//只是与某个客户端断开
}
//5、服务器关闭
// ss.close();
}
@Test
public void client()throws Exception{
//1、创建一个Socket,要指定服务器的IP和端口号
Socket socket = new Socket("192.168.24.71",9090);
//2、接收消息
InputStream is = socket.getInputStream();
byte[] data = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while((len= is.read(data)) !=-1){
sb.append(new String(data,0,len));
}
System.out.println("客户端收到的消息:" + sb);
//3、发送消息
String info = "马上吃饭了";
OutputStream out = socket.getOutputStream();
out.write(info.getBytes());
//3、关闭连接
socket.close();
}
}
-
示例二
package com.atguigu.tcp2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import org.junit.Test;
public class TestTCP2 {
@Test
public void server()throws Exception{
//1、创建ServerSocket ServerSocket server = new ServerSocket(9999); while(true){ //2、等待客户端的连接,接收客户端的连接 Socket socket = server.accept(); String clientIp = socket.getInetAddress().getHostAddress(); System.out.println(clientIp+"上线了"); //每一个客户端需要一个线程单独维护它的通信,“同时”与服务器通信的效果 new MessageHandler(socket).start(); }
}
//和服务器连接上以后,从键盘输入消息,给服务器发送,一直到从键盘输入byebye,在与服务端口连接
@Test
public void client()throws Exception{
//1、连接服务器 Socket socket = new Socket("192.168.24.71",9999); OutputStream out = socket.getOutputStream(); //2,从键盘输入给服务器发送 Scanner input = new Scanner(System.in); while(true){ System.out.println("输入要发送的内容:"); String info = input.nextLine(); if("byebye".equals(info)){ break; } //给服务器发送 out.write((info+"\n").getBytes()); } //3、断开 socket.close();
}
}
class MessageHandler extends Thread{
private Socket socket;
public MessageHandler(Socket socket) {
super(); this.socket = socket;
}
public void run(){
try { //3、和一个客户端多次通信,接收到消息后,在控制台打印 InputStream input = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(input); BufferedReader br = new BufferedReader(isr); String str; while((str = br.readLine())!=null){ System.out.println(socket.getInetAddress().getHostAddress() +"说:"+ str); } //4、断开 socket.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
-
示例三:群聊
-
服务器
package com.atguigu.tcp2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import org.junit.Test;
public class TestTCP2 {
@Test
public void server()throws Exception{
//1、创建ServerSocket ServerSocket server = new ServerSocket(9999); while(true){ //2、等待客户端的连接,接收客户端的连接 Socket socket = server.accept(); String clientIp = socket.getInetAddress().getHostAddress(); System.out.println(clientIp+"上线了"); //每一个客户端需要一个线程单独维护它的通信,“同时”与服务器通信的效果 new MessageHandler(socket).start(); }
}
//和服务器连接上以后,从键盘输入消息,给服务器发送,一直到从键盘输入byebye,在与服务端口连接
@Test
public void client()throws Exception{
//1、连接服务器 Socket socket = new Socket("192.168.24.71",9999); OutputStream out = socket.getOutputStream(); //2,从键盘输入给服务器发送 Scanner input = new Scanner(System.in); while(true){ System.out.println("输入要发送的内容:"); String info = input.nextLine(); if("byebye".equals(info)){ break; } //给服务器发送 out.write((info+"\n").getBytes()); } //3、断开 socket.close();
}
}
class MessageHandler extends Thread{
private Socket socket;
public MessageHandler(Socket socket) {
super(); this.socket = socket;
}
public void run(){
try { //3、和一个客户端多次通信,接收到消息后,在控制台打印 InputStream input = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(input); BufferedReader br = new BufferedReader(isr); String str; while((str = br.readLine())!=null){ System.out.println(socket.getInetAddress().getHostAddress() +"说:"+ str); } //4、断开 socket.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
-
客户端
package com.atguigu.tcp3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;
/*
-
*/
public class TestTCPClient{
public static void main(String[] args) throws Exception{
//1、连接服务器
Socket socket = new Socket("192.168.24.71",9090);
//2、创建两个线程,一个收,一个发
SendThread send = new SendThread(socket);
send.start();
RecevierThread r = new RecevierThread(socket);
r.start();
send.join();
r.setExit(true);
//3、关闭
socket.close();
}
}
class SendThread extends Thread{
private Socket socket;
public SendThread(Socket socket) {
super();
this.socket = socket;
}
@Override
public void run() {
try {
OutputStream output = socket.getOutputStream();
PrintStream ps = new PrintStream(output);
Scanner input = new Scanner(System.in);
while(true){
System.out.println("请输入要发送的内容:");
String info = input.nextLine();
if("bye".equals(info)){
break;
}
//给服务器发送
ps.println(info);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class RecevierThread extends Thread{
private Socket socket;
private boolean exit = false;
public RecevierThread(Socket socket) {
super();
this.socket = socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String str;
while(exit==false){
try {
str = br.readLine();
} catch (SocketException e) {
break;
}
if(str==null){
break;
}
System.out.println("收到的消息:" + str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void setExit(boolean exit) {
this.exit = exit;
}
}
2.3 UDP编程步骤
-
发送端
-
1、创建一个DatagramSocket
-
2、准备发送的数据,并且打包
-
DatagramPacket
- 要指定:发送的数据,长度,接收方的IP,接收方的端口号
-
-
3、通过DatagramSocket的send(数据报)
-
4、关闭
-
-
接收端
-
1、创建一个DatagramSocket
- 要指定 监听的端口号
-
2、准备一个DatagramPacket,用来接收数据
- 要指定装数据一个字节数组,以及长度
-
3、通过DatagramSocket的receive(数据报)
-
4、拆解数据
- 通过DatagramPacket对象.getData()数据,DatagramPacket对象.getLength()实际接收的数据长度
-
5、关闭
-
-
示例代码
package com.atguigu.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import org.junit.Test;
/*
-
UDP:非面向连接的
-
- 有发送端和接收端两个应用程序
*/
public class TestUDP {
@Test
public void send()throws Exception{
//1、创建Socket
DatagramSocket ds = new DatagramSocket();
//2、把数据打包成一个数据报,包
String str = "双十二购物快乐";
byte[] bytes = str.getBytes();
InetAddress ip = InetAddress.getByName("192.168.24.71");
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, ip,8989);
//3、通过socket发送出去
ds.send(dp);
System.out.println("发送完毕");
//4、释放资源
ds.close();
}
@Test
public void reveive()throws Exception{
//1、创建Socket
DatagramSocket ds = new DatagramSocket(8989);//为它指定一个端口号,在端口号一直监听着
//2、先创建一个数据报等着
byte[] data = new byte[1024];
DatagramPacket dp = new DatagramPacket(data, data.length);
//3、准备接受数据,从socket中接收数据,如果此时没有数据,这句代码会阻塞
ds.receive(dp);
//4、拆出数据
String str = new String(dp.getData(),0,dp.getLength());
System.out.println("收到的数据是:" + str);
//5、关闭
ds.close();
}
}
2.4 URL编程
-
在TCP的基础上
-
服务器端
- Web服务器
-
客户端
-
1、创建URL的对象
-
URL url = new URL(网址);
- 网址:协议://主机名:端口号/文件路径名?参数名=参数值&参数名=参数值…
- 例如:http://localhost:8080/1108web/index.html
- 例如:http://localhost:8080/1108web/login?username=xx&password=xx
-
-
2、与服务器建立连接
-
InputStream is = url.openStream();
-
这种方式只能使用get方法与服务器进行通信
- 如果要给服务器传参数只能在网址后面通过?参数名=参数值&参数名=参数值…
-
-
HttpURLConnection tc = (HttpURLConnection)url.openConnection();
-
这种方式可以使用post方法与服务器进行通信
- 如果要给服务器传数据,那么需要hc.setDoOutput(true);
- 然后用OutputStream进行发送数据
-
-
-
3、处理接收到数据
-
-
-
示例代码
-
示例一
package com.atguigu.url;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
/*
-
tomcat:是一个服务器
-
浏览器:客户端
*/
public class TestURL {
public static void main(String[] args) throws Exception{
//自定义客户端 URL url = new URL("http://192.168.24.71:8080/1108JavaWeb/index.html"); /*System.out.println("协议:" + url.getProtocol()); System.out.println("主机名:" + url.getHost()); System.out.println("端口号:" + url.getPort()); System.out.println("路径名:" + url.getPath());*/ InputStream input = url.openStream(); InputStreamReader isr = new InputStreamReader(input); BufferedReader br = new BufferedReader(isr); String str ; while((str=br.readLine())!=null){ System.out.println(str); }
}
}
-
-
示例二:get
package com.atguigu.url;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
public class TestURL2 {
public static void main(String[] args) throws Exception{
URL url = new URL("http://192.168.24.71:8080/myweb/login?username=admin&pass=123"); InputStream input = url.openStream(); InputStreamReader isr = new InputStreamReader(input); BufferedReader br = new BufferedReader(isr); String str ; while((str=br.readLine())!=null){ System.out.println(str); }
}
}
-
示例三:post
package com.atguigu.url;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class TestURL3 {
public static void main(String[] args) throws Exception{
URL url = new URL("http://192.168.24.71:8080/myweb/login"); HttpURLConnection hc = (HttpURLConnection) url.openConnection(); hc.setDoOutput(true); OutputStream output = hc.getOutputStream(); PrintStream ps = new PrintStream(output);
// output.write(“username=chai&pass=123”.getBytes());
ps.println("username=chai&pass=123"); InputStream input = hc.getInputStream(); InputStreamReader isr = new InputStreamReader(input); BufferedReader br = new BufferedReader(isr); String str ; while((str=br.readLine())!=null){ System.out.println(str); }
}
}
-