网络编程三要素
IP地址:设备在网络中的唯一标识
- IPv4,32位的IP地址,常用点分十进制方便书写
- IPv6,128位的IP地址,常用冒分十六进制方便书写
- 常用命令,在cmd中可以用
ipcofig
查看本机IP地址,用ping IP地址/域名
可以检测当前与某个设备是否可以连通
- 特殊的IP地址:127.0.0.1称为回送地址又叫本地回环地址,可以代表本机IP地址,一般用作测试
- inetAddress类
- 不提供构造方法,可以通过提供的一些静态方法获取一个对象,这些静态方法需要传入主机名或IP地址
- 常用方法有
String getHostName()
和String getHostAddress()
分别获取主机名和IP地址
- 端口号:应用程序在设备中唯一标识
- 两个字节表示的整数,范围时0~65535
- 其中0~1023之间的端口号用于知名网络服务或应用,自用的需要在1024以上
- 注意一个端口号只能被一个应用程序使用
- 协议:数据在传输过程中遵守的规则
- UDP,用户数据报协议,面向无连接的通信协议,速度快一次最多发送64K的数据,数据不安全易丢失
- TCP,传输控制协议,面向连接的通信协议,速度慢,没有大小限制,数据安全
UDP通信程序
发送数据步骤
- 创建发送端DatagramSocket对象
- 创建数据并打包DatagramPacket对象
- 调用DatagramSocket对象的方法发送数据
- 释放资源
Client
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| DatagramSocket ds = new DatagramSocket();
String data = "这是我发送的数据"; byte[] bytes = data.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,10000);
ds.send(dp);
ds.close();
|
接受数据步骤
创建接收端DatagramSocket对象
创建DatagramPacket对象接收数据
调用DategramSocket的方法将数据装入DatagramPacket对象
解析数据
释放资源
Service
1 2 3 4 5 6 7 8 9 10 11 12
| DatagramSocket ds = new DatagramSocket(10000);
byte[] bytes = new byte[1024]; DatagramPacket dp = new DatagramPacket(bytes,bytes.length); ds.receive(dp);
byte[] data = dp.getData(); System.out.println(new String(data,0,dp.getLength()));
ds.close();
|
三种通信方式
单播,一对一
组播,一对多
组播地址是224.0.0.0~ 239.255.255.255,其中224.0.0.0~224.0.0.255是预留的不能使用,只能从224.0.1.0开始使用
组播发送端与单薄类似,但是发送的地址应该是组播地址
组播接收端使用的是MulticastSocket对象而不是DatagramSocket
接收端需要将本机添加入组播中才能收到数据
广播,一对全部
- 广播地址是255.255.255.255
- 广播的发送端与单播一样,只是将地址换成广播地址即可
- 广播的接收端和单播一样
TCP通信程序
TCP通信协议是可靠的网络协议,,它在通信的两端各建立一个Socket对象,通信之前要保证连接已经建立,通过Socket产生IO流来进行网络通信
客户端发送数据步骤
- 创建客户端Socket对象,与指定的服务端连接,
public Socket(String host,int port)
- 利用Socket对象获取输出流,
OutputStream getOutputStream()
,利用获取到的输出流对象的write()
方法写数据
- 释放资源,
void close()
Client
1 2 3 4 5 6 7 8 9 10 11 12
| Socket socket = new Socket("127.0.0.1",10001);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("helloworld".getBytes());
outputStream.close(); socket.close();
|
服务端接收数据步骤
- 创建ServerSocket对象,
public ServerSocket(int port)
- 监听客户端连接,获取Socket对象,
Socket accept()
- 获取输入流,读数据,
InputStream getyInputStream()
- 释放资源,
void close()
Server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| ServerSocket serverSocket = new ServerSocket(10001);
Socket accept = serverSocket.accept();
InputStream inputStream = accept.getInputStream();
int b; while((b = inputStream.read()) != -1){ System.out.print((char)b); }
inputStream.close(); serverSocket.close();
|
文件传输
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import java.io.*; import java.net.Socket;
public class Client { public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",10001); BufferedInputStream bis = new BufferedInputStream(new FileInputStream("image.jpg")); OutputStream os = socket.getOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(os);
int b; while((b = bis.read()) != -1){ bos.write(b); } socket.shutdownOutput(); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line; while((line = br.readLine()) != null){ System.out.println(line); } bis.close(); br.close(); socket.close(); } }
|
服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import java.io.*; import java.net.ServerSocket; import java.net.Socket;
public class Server { public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10001); Socket accept = ss.accept(); InputStream is = accept.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg"));
int b; while ((b = bis.read()) != -1) { bos.write(b); } BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream())); bw.write("文件上传成功"); bw.newLine(); bw.flush();
bos.close(); accept.close();
ss.close(); } }
|
使用while循环,UUID,多线程和线程池来优化服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| public class Server { public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10001); ThreadPoolExecutor tpe = new ThreadPoolExecutor( 3, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy() ); while (true) { Socket accept = ss.accept(); ThreadSocket ts = new ThreadSocket(accept); tpe.submit(ts); } } }
class ThreadSocket implements Runnable{
private Socket accept; public ThreadSocket(Socket accept) { this.accept = accept; }
@Override public void run() { BufferedOutputStream bos = null; try { InputStream is = accept.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); bos = new BufferedOutputStream(new FileOutputStream(UUID.randomUUID().toString() + ".jpg"));
int b; while ((b = bis.read()) != -1) { bos.write(b); }
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream())); bw.write("文件上传成功"); bw.newLine(); bw.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if(bos != null){ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } if(accept != null){ try { accept.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
|