视频链接:黑马Java网络编程教程
一,网络编程三要素
1,IP
(1)ipv4的一些小细节
(2)InetAddress类的使用
2,端口号
3,协议
二,UDP协议
1,发送数据
package Net.UDP;
import java.io.IOException;
import java.net.*;
public class SendMessage {
public static void main(String[] args) throws IOException {
//1,创建DatagramSocket对象(快递公司)
//细节:
//绑定端口,以后我们就是通过这个端口往外发送
//空参:所有可用的端口中随机选一个使用
//有参:指定端口进行绑定
DatagramSocket DS=new DatagramSocket();
//2,打包数据
String str ="你好啊!!";
byte[] bytes=str.getBytes();
InetAddress address=InetAddress.getByName("127.0.0.1");
int port=8888;
DatagramPacket DP=new DatagramPacket(bytes,bytes.length,address,8888);
//3,发送数据
DS.send(DP);
//4,释放资源
DS.close();
}
}
2,接收数据
package Net.UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class ReceiveMessage {
public static void main(String[] args) throws IOException {
//1,创建DatagramSocket对象(快递公司)
//细节:
//在接收的时候一定要绑定端口
//绑定的端口要和发送的端口一致
DatagramSocket DS= new DatagramSocket(8888);
//2,接受数据包
byte[] bytes=new byte[1024];
DatagramPacket DP=new DatagramPacket(bytes,bytes.length);
DS.receive(DP);//该方法是阻塞的
//3,解析数据包
byte[] data=DP.getData();
int len=DP.getLength();
InetAddress address=DP.getAddress();
int port=DP.getPort();
System.out.println("接收到数据:"+new String(data,0,len));
System.out.println("该数据是从:"+address+"这台电脑的"+port+"端口发送来的");
//4,释放资源
DS.close();
}
}
3,UDP的三种通信
(1)单播
平常写的代码就是单播。
(2)组播
组播发送端
- 添加了MulticastSocket对象
- 改变了address的值
组播接收端
- 添加了MulticastSocket对象
- 改变了address的值
- joinGroup(address)
(3)广播
- 只需在发送数据端,修改为以下代码
三,TCP协议
1,服务端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
//1,创建对象ServerSocket
ServerSocket serverSocket=new ServerSocket(8888);
//2,监听客户端的连接
Socket socket=serverSocket.accept();//阻塞
//3,从连接通道中获取输入流读取数据
/*
InputStream inputStream=socket.getInputStream();
//将字节流编程字符流,不然中文乱码
InputStreamReader inputStreamReader=new InputStreamReader(inputStream);
//添加缓冲流,提高效率
BufferedReader bufferedReader=new BufferedReader(inputStreamReader)
*/
//作用等同于以上三行
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
int b;
while((b = bufferedReader.read())!=-1){
System.out.println((char) b);
}
//4,释放资源
socket.close();
serverSocket.close();
}
}
2,客户端
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
//1,细节:在创建对象的同时会连接服务端
// 如果连接不上,代码会报错
Socket socket=new Socket("127.0.0.1",8888);
//2,可以从连接通道中获取输出流
OutputStream os=socket.getOutputStream();
//写入数据
os.write("hello!你好哇".getBytes());
//3,释放资源
os.close();
socket.close();
}
}
3,三次握手
4,四次挥手
四,综合练习
1,服务端
MyRannable
import java.io.*;
import java.net.Socket;
import java.util.UUID;
public class MyRunable implements Runnable{
Socket socket;
public MyRunable(Socket socket){//利用构造函数传递参数
this.socket=socket;
}
@Override
public void run(){
try {
//3,读取数据并保存到本地文件中
BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
String name = UUID.randomUUID().toString().replace("-","");//防止文件重名
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("serverdir\\"+name+".jpg"));
int len;
byte[]bytes=new byte[1024];
while ((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
//4,回写数据
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("上传成功");
bw.newLine();
bw.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
//5,释放资源
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
Server
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
import java.util.concurrent.*;
public class Server {
public static void main(String[] args) throws IOException {
//客户端:将本地文件上传到服务器,接收服务器的反馈
//服务端:接收客户端上传的数据,上传完毕后给出反馈
//创建线程池对象
ThreadPoolExecutor pool=new ThreadPoolExecutor(
3,//核心线程数
16,//线程池的总大小
60,//空闲存活时间
TimeUnit.SECONDS,//时间单位
new ArrayBlockingQueue<>(2),//队列
Executors.defaultThreadFactory(),//线程工厂,让线程池如何创建线程
new ThreadPoolExecutor.AbortPolicy()//阻塞队列
);
//1,创建对象并绑定端口
ServerSocket ss=new ServerSocket(8888);
while(true){
//2,等待客户端来连接
Socket socket=ss.accept();
//开启一条线程
//一个用户就对应服务端的一条线程
//new Thread(new MyRunable(socket)).start();
pool.submit(new MyRunable(socket));
}
}
}
2,客户端
client
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
//客户端:将本地文件上传到服务器,接收服务器的反馈
//服务端:接收客户端上传的数据,上传完毕后给出反馈
//1,创建Socket对象,并连接服务器
Socket socket=new Socket("127.0.0.1",8888);
//2,读取本地文件中的数据,并写到服务器
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("clientdir/a.jpg"));
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
byte[]bytes=new byte[1024];
int len;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
//往服务器写出结束标记
socket.shutdownOutput();
//3,接收服务器的回写数据
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=br.readLine();
System.out.println(line);
//4,释放资源
socket.close();
}
}