Java

网络编程

概念

  • 网络编程可以让程序与网络上的其他设备中的程序进行数据交互

网络通信基本模式

  • 常见的通信模式有如下两种形式,Client-Server(CS),Browser/Server(BS)
Client-Server
Client
  • 需要程序员开发实现
  • 用户需要安装客户端
Server
  • 需要程序员开发实现
Browser-Server
Browser
  • 不需要程序员开发
  • 用户需要安装浏览器
Server
  • 需要程序员开发实现

学习要求

网络通信三要素 UDP通信 TCP通信 即时通信 模拟BS系统
一个消息发送给对方需要哪些关键因素 消息直接发送给对象,不确认对方是否在线,不做消息确认 基于可靠传输的方式进行的通信模式。解决不同场景的通信需求 如何实现即时通信,具体是如何实现的 WEB系统是如何支持访问到网页的,具体是如何与服务器通信的

网络三要素

三要素概述

IP地址:设备在网络中的地址,是唯一的标识

端口:应用程序在设备中唯一的标识

协议:数据在网络传输的规则,常见的协议有UDP协议和TCP协议

要素一:IP地址
  • IP(internet Protocol):全程“互联网协议地址”,是分配给上网设备的唯一标志
  • 常见的IP分类为:IPv4和IPv6
  • IPv4 (四个字节)32位
  • IPv6:128位(16个字节)
    • IPv6分成8个整数,每个整数 用四个十六进制位表示,数之间用冒号(:)分开
IP地址基本寻路

采用域名

IP地址形式
  • 公网地址和私有地址(局域网使用)
  • 192.168.开头的就是常见的局域网地址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用
IP常用命令
  • ipconfig:查看本机IP地址
  • ping IP地址:检查网络是否连通
特殊IP地址
  • 本机127.0.0.1或者localhost:称为回送地址也可称本地回环地址,只会寻找当前所在本机

IP地址操作类——inetAddress

InetAddress的使用
  • 此类表示Internet协议(IP)地址
InetAddress API如下
名称 说明
public static InetAddress getLocalHost() 返回本主机的地址对象
public static InetAddress getByName(String host) 得到指定主机的IP地址对象,参数是域名或者IP地址
public Sting getHostName() 获取此IP地址的主机名
public Sting getHostAddress() 返回IP地址字符串
public boolean isReachable(int timeout) 在指定毫秒内连通IP地址对应的主机,返回true
package com.yu.Day1012Demo;

import java.net.InetAddress;

public class InetAddressDemo01 {
public static void main(String[] args) throws Exception{
//1. 获取本机地址对象
InetAddress ia = InetAddress.getLocalHost();
System.out.println(ia);
System.out.println(ia.getHostName());
System.out.println(ia.getHostAddress());
//输出内容是电脑蓝牙名和IP地址 //2.获取域名对象的IP地址
InetAddress ia2 = InetAddress.getByName("www.baidu.com");
System.out.println(ia2); //3. 获取公网IP对象
InetAddress ia3 = InetAddress.getByName("110.242.68.4");
System.out.println(ia3); //4. 判断是否连通,ping 5s之前测试是否连通
System.out.println(ia3.isReachable(5000));
}
}
总结
  1. IP地址的代表类是

    InetAddress类

  2. 如何获取本机IP对象

    • public static InetAddress getLocalHost()
  3. 如何判断与该IP地址对象是否互通

    • public boolean isReachable(int timeout)

要素二:端口号

  • 端口号:标识正在计算机设备上运行的进程(程序),被规定为一个16为的二进制,范围0-65535
端口类型
  • 周知端口:0-1023,被预先定义的知名应用占用(如HTTP占用80,FTP占用21)
  • 注册端口:1024-49151,分配给iyh进程或某些应用程序。(如Tomcat占用8080,MySQL占用3306)
  • 动态端口:49152-65535,之所以称之为动态端口,是因为它一般不固定分配某种进程,而是动态分配

注意:我们自己开发的程序注册端口,且一个设备中不能出现两个程序端口号一样,否则出错

总结
  1. 端口号的作用是什么

    • 唯一标识正在计算机设备上运行的进程(程序)
  2. 一个设备中,能否出现两个应用程序的端口号一样,为什么?
    • 不可以,如果一样会出现端口号冲突错误

要素三:协议

通信协议
  • 连接和通信数据的规则被称为网络通信协议
网络通信协议有两套参考模型
  • OSI参考模型:世界上互联协议标准,全球通信规范,由于此模型过于理想化未能在因特网上进行广泛推广
  • TCP/IP参考模型(或TCP/IP协议):事实上的国际标准
OSI参考模型 TCP/IP参考模型 各层对应 面向操作
应用层
表示层
会话层
应用层 HTTP、FTP、DNS、SMTP 应用程序需要关注的:浏览器、邮箱、程序员一般在这一层开发
传输层 传输层 TCP、UDP 选择使用的TCP,UDP协议
网络层
数据链路层
网络层 IP、ICMP 封装源和目标IP,进行路径选择
物理层 数据链路层——物理 物理寻址、比特流 物理设备中传输
传输层的两个常见协议
  • TCP(Transmission Control Protocol):传输控制协议

    • UDP(User Datagram Protocol):用户数据报协议
TCP协议特点
  • 使用TCP协议,必须双方先建立连接,它是一种面向连接可靠通信协议
  • 传输前,采用“三次握手”方式建立连接,所以是可靠的
  • 在连接中可进行大量数据的传输
  • 连接、发送数据都需要确认、且传输完毕后、还需释放已建立的连接,通信效率较低
TCP协议通信场景
  • 对信息安全要求较高的场所,例如:文件下载、金融等数据通信
UDP协议
  • UDP是一种无连接不可靠传输的协议
  • 将数据源IP、目的地IP和端口封装成数据包,不需要建立连接
  • 每个数据包的大小限制在64kb内
  • 发送不管对方是否准备号,接收方收到也不确认,故而不可靠的
  • 可以广播发送,发送数据结束时无需释放资源,开销小,速度快
UDP协议通信场景
  • 语音通话,视频通话等

UDP通信

特点
  • UDP是一种无连接不可靠传输的协议
  • 将数据源IP、目的地IP和端口封装成数据包,不需要建立连接
  • 每个数据包的大小限制在64kb内
  • 发送不管对方是否准备号,接收方收到也不确认,故而不可靠的
DatagramPacket:数据包对象
构造器 说明
public DatagramPacket(byte[] buf,int length,InetAddress address,int port) 创建发送端数据包对象
buf:要发送的内容,字节数组
length:要发送内容的字节长度
address:接收端的IP地址对象
port:接收端的端口号
public DatagramPacket(byte[] buf,int length) 创建接收端的数据包对象
buf:用来存储接收来的内容
length:能够接收内容长度
DatagramPacket常用方法
方法 说明
public int getLength() 获得实际接收到的字节个数
DatagramSocket:发送端和接收端对象
构造器 说明
public DatagramSocket() 创建发送端的Socket对象,系统会随机分配一个端口号
public DatagramSocket(int port) 创建接收端的Socket对象并指定端口号
DatagramSocket类成员方法
方法 说明
public void send(DatagramPacket dp) 发送数据包
public void receive(DatagramPacket p) 接收数据包
总结
  1. UDP发送端和接收端的对象是哪个?

    • public DatagramSocket():创建发送端的Socket对象
    • public DatagramSocket(int port):创建接收端的Socket对象
  2. 数据包对象是哪个?
    • DatagramPacket
  3. 如何发送、接收数据包?
    • 使用DatagramSocket的如下方法
    • public void send(DatagramPacket dp):发送数据包
    • public void receive(DatagramPacket dp):接收数据包
  4. 先执行接收端在执行发送端
package com.yu.Day1012Demo;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress; public class ClientDemo01 {
public static void main(String[] args) throws Exception{
//1.创建发送端对象,发送端自带默认端口号
DatagramSocket socket = new DatagramSocket(); //2. 创建一个数据包对象封装数据
/**
* public DatagramPacket(byte[] buf,
* int length,
* InetAddress address,
* int port)
* 参数一 封装发送的数据
* 参数二:发送数据的大小
* 参数三:服务器的Ip地址
* 参数四:服务端端口号
*/
byte[] bytes = "我是一颗快乐的韭菜,你想吃吗?".getBytes();
DatagramPacket packet = new DatagramPacket(bytes,bytes.length,
InetAddress.getLocalHost(),8888);
//3.发送数据出去
socket.send(packet);
socket.close();
}
}
package com.yu.Day1012Demo;

import java.net.DatagramPacket;
import java.net.DatagramSocket; public class ServerDemo01 {
public static void main(String[] args) throws Exception{
//1.创建接收端对象,连接端口
DatagramSocket socket = new DatagramSocket(8888); //2.创建一个数据包对象接收数据
byte[] bytes = new byte[1034*64];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length); //3. 等待接收数据
socket.receive(packet); //4. 取出数据即可
int len = packet.getLength();
String sr = new String(bytes,0,len);
System.out.println(sr); //获取发送端的ip和端口
String ip = packet.getSocketAddress().toString();
System.out.println(ip);
int port = packet.getPort();
System.out.println(port);
socket.close();
}
}

多发多收

案例:使用UDP通信实现:多发多收消息
package com.yu.Day1012Demo;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner; public class ClientDemo02 {
public static void main(String[] args) throws Exception{
//1.创建发送端对象,发送端自带默认端口号
DatagramSocket socket = new DatagramSocket(); Scanner sc = new Scanner(System.in); while (true) {
System.out.print("请输入");
String msg = sc.nextLine();
if("exit".equals(msg)){
System.out.println("离线成功!!!");
socket.close();
break;
}
//2. 创建一个数据包对象封装数据
byte[] bytes = msg.getBytes();
DatagramPacket packet = new DatagramPacket(bytes,bytes.length,
InetAddress.getLocalHost(),8888);
//3.发送数据出去
socket.send(packet);
}
}
}
package com.yu.Day1012Demo;

import java.net.DatagramPacket;
import java.net.DatagramSocket; public class ServerDemo02 {
public static void main(String[] args) throws Exception{
//1.创建接收端对象,连接端口
DatagramSocket socket = new DatagramSocket(8888); //2.创建一个数据包对象接收数据
byte[] bytes = new byte[1024*64];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length); while (true) {
//3. 等待接收数据
socket.receive(packet); //4. 取出数据即可
int len = packet.getLength();
String sr = new String(bytes,0,len);
String ip = String.valueOf(packet.getAddress());
int port = packet.getPort();
System.out.println("发送方的ip地址为"+ip+"端口号为:"+port+"内容为"+sr);
} }
}
总结
  1. UDP的接收端为什么可以接收很多发送端的消息

    • 接收端只负责接收数据包,无所谓是哪个发送端的数据包

广播、组播

UDP的三种通信方式
  • 单播:单台主机与单台主机之间的通信
  • 广播:当前主机与所在网络中的所有主机通信
  • 组播:当前主机与选定的一组主机的通信
UDP如何实现广播
  • 使用广播地址:255.255.255.255
  • 具体操作
    1. 发送端发送的数据包的目的地写的是广播地址,且指定端口。(255.255.255.255 9999)
    2. 本机所在网段的其他主机的程序只要能匹配端口成功即可收到消息了(9999)
UDP如何实现组播
  • 使用组播地址:224.0.0.0~239.255.255.255
  • 具体操作
    1. 发送端的数据包的目的地是组播IP(例如 224.0.1.1 9999)
    2. 接收端必须绑定该组播IP(224.0.1.1),端口还有对应发送端的目的地端口9999,这样即可接收该组播消息
    3. DatagramSocket的子类MulticastSocket可以在接收端绑定组播ip
package com.yu.Day1012Demo;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner; public class ClientDemo04 {
public static void main(String[] args) throws Exception{
//1.创建发送端对象,发送端自带默认端口号
DatagramSocket socket = new DatagramSocket(); Scanner sc = new Scanner(System.in); while (true) {
System.out.print("请输入");
String msg = sc.nextLine();
if("exit".equals(msg)){
System.out.println("离线成功!!!");
socket.close();
break;
}
//2. 创建一个数据包对象封装数据
byte[] bytes = msg.getBytes();
DatagramPacket packet = new DatagramPacket(bytes,bytes.length,
InetAddress.getByName("224.0.1.1"),9999);
//3.发送数据出去
socket.send(packet);
}
}
}
package com.yu.Day1012Demo;

import java.net.*;

public class ServerDemo04 {
public static void main(String[] args) throws Exception{
//1.创建接收端对象,连接端口
MulticastSocket socket = new MulticastSocket(9999);
//把当前接收端加入到一个组播中去,绑定对应的组播消息的组播ip
//过时
// socket.joinGroup(InetAddress.getByName("224.0.1.1"));
socket.joinGroup(new InetSocketAddress(InetAddress.getByName("224.0.1.1"),9999),
NetworkInterface.getByInetAddress(InetAddress.getLocalHost()));
//2.创建一个数据包对象接收数据
byte[] bytes = new byte[1024*64];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length); while (true) {
//3. 等待接收数据
socket.receive(packet); //4. 取出数据即可
int len = packet.getLength();
String sr = new String(bytes,0,len);
String ip = String.valueOf(packet.getAddress());
int port = packet.getPort();
System.out.println("发送方的ip地址为"+ip+"端口号为:"+port+"内容为"+sr);
} }
}

TCP通信协议

*** 注意:在Java中只有使用java.net.Sokcket类实现通信,底层即是使用了TCP协议***

Socket
构造器 说明
public Socket(String host,int port) 创建发送端的Socket对象与服务端连接,参数为服务端程序的IP和端口号
Socket类成员方法
方法 说明
OutputStream getOutputStream() 获得字节输出流对象
InputStream getInputStream() 获得字节输出流对象
总结
  1. TCP通信的客户端的代表类是谁?

    • Socket类
    • public Socket(String host,int port)
  2. TCP通信如何使用Socket管道发送,接收数据。
    • OutputStream getOutputStream():获得字节输出流对象(发)
ServerSocket (服务端)
构造器 说明
public ServerSocket(int port) 注册服务端端口
ServerSocket类成员方法
方法 说明
public Socket accept() 等待接收客户端的Socket通信连接
连接成功返回Socket对象与客户端建立端到端通信
总结
  1. TCP通信服务端用的代表类

    • ServerSocket类,注册端口
    • 调用accept()方法阻塞等待接收客户端连接,得到Socket对象
  2. TCP通信的基本原理
    • 客户端怎么发,服务端就应该怎么收
    • 客户端如果没有消息,服务端会进入阻塞等待
    • Socket一方关闭或者出现异常,对方Socket也会失效或者出错
package com.yu.Day1012Demo;

import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket; public class ClientDemo05 {
public static void main(String[] args) throws Exception{
//1. 创建Socket通信管道请求服务其的连接
//public Socket(String host.int port)
//参数一:服务器的IP地址
//参数二:服务器的端口
Socket socket = new Socket("127.0.0.1",7777);
//2.从socket通信管道中得到一个字节输出流负责发送数据
OutputStream os = socket.getOutputStream();
//3. 把低级的字节流包装成打印流
PrintStream ps = new PrintStream(os);
//4.发送消息
ps.println("我是TCP的客户端,我已经与你对接,并发出通话:约不?");
ps.flush();
//关闭通话
socket.close(); }
}
package com.yu.Day1012Demo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket; public class ServerDemo05 {
public static void main(String[] args) throws Exception{
//1.注册窗口
ServerSocket serverSocket = new ServerSocket(7777);
//2.必须调用accept方法。等待接收客户端的Socket连接请求,建立Socket通信管道
Socket socket = serverSocket.accept();
//3.从Socket通信管道中得到一个字节输出流
InputStream is = socket.getInputStream();
//4.把字节输入流包装成缓冲字符输入流进行消息的接收
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//5.按照行读取消息
String msq;
while ((msq = br.readLine())!=null) {
System.out.println(socket.getRemoteSocketAddress()+"说了:"+msq);
}
}
}

TCP通信实现多发多收

群发多收

package com.yu.Day1012Demo;

import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner; public class ClientDemo07 {
public static void main(String[] args) throws Exception{
//1. 创建Socket通信管道请求服务其的连接
//public Socket(String host.int port)
//参数一:服务器的IP地址
//参数二:服务器的端口
Socket socket = new Socket("127.0.0.1",7777);
//2.从socket通信管道中得到一个字节输出流负责发送数据
OutputStream os = socket.getOutputStream();
//3. 把低级的字节流包装成打印流
PrintStream ps = new PrintStream(os);
Scanner sc = new Scanner(System.in); while (true) {
System.out.print("请输入要发送的消息:");
String msq = sc.nextLine();
//4.发送消息
ps.println(msq+"爱你");
ps.flush();
}
//关闭通话
// socket.close(); }
}
package com.yu.Day1012Demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket; public class ServerReaderThread extends Thread {
private Socket socket;
public ServerReaderThread(Socket socket){
this.socket = socket;
} @Override
public void run() {
try {
InputStream is = socket.getInputStream();
//4.把字节输入流包装成缓冲字符输入流进行消息的接收
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//5.按照行读取消息
String msq;
while ((msq = br.readLine())!=null) {
System.out.println(socket.getRemoteSocketAddress()+"说了:"+msq);
}
} catch (Exception e) {
System.out.println(socket.getRemoteSocketAddress()+"下线了!!!");
}
}
}
package com.yu.Day1012Demo;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket; public class ServerDemo07 {
public static void main(String[] args) throws Exception{
//1.注册窗口
ServerSocket serverSocket = new ServerSocket(7777);
//2.必须调用accept方法。等待接收客户端的Socket连接请求,建立Socket通信管道
while (true) {
Socket socket = serverSocket.accept();
System.out.println(socket.getRemoteSocketAddress()+"上线了");
new ServerReaderThread(socket).start();
} }
}
总结
  1. 本次是如何实现服务端接收多个客户端的消息的

    • 主线程定义了循环负责接收客户端Socket管道连接
    • 没接收到一个Socket通信管道后分配一个独立的线程负责它

TCP通信-使用线程池优化

客户端同上
package com.yu.Day1012Demo.Executor;

import com.yu.Day1012Demo.ServerReaderThread;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*; public class ServerDemo {
private static ExecutorService pool = new ThreadPoolExecutor(
3,5,6, TimeUnit.SECONDS,new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) throws Exception{
System.out.println("===服务器启动成===");
//1.注册窗口
ServerSocket serverSocket = new ServerSocket(7777);
//2.必须调用accept方法。等待接收客户端的Socket连接请求,建立Socket通信管道
while (true) {
Socket socket = serverSocket.accept();
System.out.println(socket.getRemoteSocketAddress()+"上线了");
//负责读取消息
Runnable target = new ServerReaderRunnable(socket);
pool.execute(target);
}
}
}
package com.yu.Day1012Demo.Executor;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket; public class ServerReaderRunnable implements Runnable{
private Socket socket;
public ServerReaderRunnable(Socket socket) {
this.socket = socket;
} @Override
public void run() {
try {
InputStream is = socket.getInputStream();
//4.把字节输入流包装成缓冲字符输入流进行消息的接收
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//5.按照行读取消息
String msq;
while ((msq = br.readLine())!=null) {
System.out.println(socket.getRemoteSocketAddress()+"说了:"+msq);
}
} catch (Exception e) {
System.out.println(socket.getRemoteSocketAddress()+"下线了!!!");
}
}
}

控制了总体数量,不会让服务器负载过多而崩掉

即时通信

端口转发
  1. 即时通信是什么含义,要实现怎么样的设计?

    • 即时通信,是指一个客户端的消息发出去,其他客户端可以接收到
    • 即时通信需要进行端口转发的设计思想
    • 服务端需要把在线的Socket管道存储起来
    • 一旦收到一个消息要推送给其他管道
package com.yu.Day1012Demo.jishitongxin;

import java.io.*;
import java.net.Socket;
import java.util.Scanner; public class ClientDemo00 {
public static void main(String[] args) throws Exception{
Socket socket = new Socket("127.0.0.1",7777);
//创建一个独立的线程专门负责这个客户端的读消息(服务端随时可能转发消息过来)
new ClientReaderThread(socket).start();
OutputStream os = socket.getOutputStream();
//3. 把低级的字节流包装成打印流
PrintStream ps = new PrintStream(os);
Scanner sc = new Scanner(System.in); while (true) {
System.out.print("请输入要发送的消息:");
String msq = sc.nextLine();
//4.发送消息
ps.println(msq+"爱你");
ps.flush();
}
//关闭通话
// socket.close(); }
}
class ClientReaderThread extends Thread{
private Socket socket;
public ClientReaderThread(Socket socket){
this.socket = socket;
} @Override
public void run() {
try {
InputStream is = socket.getInputStream();
//4.把字节输入流包装成缓冲字符输入流进行消息的接收
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//5.按照行读取消息
String msq;
while ((msq = br.readLine())!=null) {
System.out.println(socket.getRemoteSocketAddress()+"说了:"+msq);
}
} catch (Exception e) {
System.out.println(socket.getRemoteSocketAddress()+"被踢出群聊!!!");
}
}
}
package com.yu.Day1012Demo.jishitongxin;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List; public class ServerDemo00 {
//定义一个静态的List集合存储当前全部在线socket管道
public static List<Socket> all_onLine_socket = new ArrayList<>();
public static void main(String[] args) throws Exception{
//1.注册窗口
ServerSocket serverSocket = new ServerSocket(7777);
//2.必须调用accept方法。等待接收客户端的Socket连接请求,建立Socket通信管道
while (true) {
Socket socket = serverSocket.accept();
System.out.println(socket.getRemoteSocketAddress()+"上线了");
all_onLine_socket.add(socket);
new ServerReaderThread(socket).start();
} }
}
class ServerReaderThread extends Thread {
private Socket socket;
public ServerReaderThread(Socket socket){
this.socket = socket;
} @Override
public void run() {
try {
InputStream is = socket.getInputStream();
//4.把字节输入流包装成缓冲字符输入流进行消息的接收
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//5.按照行读取消息
String msq;
while ((msq = br.readLine())!=null) {
System.out.println(socket.getRemoteSocketAddress()+"说了:"+msq);
//把这个消息进行端口转发给全部客户端socket管道
sendMsgToAll(msq);
}
} catch (Exception e) {
System.out.println(socket.getRemoteSocketAddress()+"下线了!!!");
ServerDemo00.all_onLine_socket.remove(socket);
}
} private void sendMsgToAll(String msq) throws Exception {
for (Socket socket : ServerDemo00.all_onLine_socket) {
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println(msq);
ps.flush();
}
}
}

模拟BS通信

实现BS开发

注意:服务器必须给浏览器响应HTTP协议格式的数据,否则浏览器不识别

package com.yu.Day1012Demo.BS;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*; public class BSserverDemo {
private static ExecutorService pool = new ThreadPoolExecutor(3,5,6, TimeUnit.SECONDS,new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory());
public static void main(String[] args) throws Exception{
ServerSocket ss = new ServerSocket(8080);
while(true){
Socket socket = ss.accept();
pool.execute(new ServerReaderRunnable(socket));
}
}
}
package com.yu.Day1012Demo.BS;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket; public class ServerReaderRunnable implements Runnable{
private Socket socket;
public ServerReaderRunnable(Socket socket) {
this.socket = socket;
} @Override
public void run() {
try {
//浏览器 已经与本线程建立了Socket管道
//相应消息给浏览器显示
PrintStream ps = new PrintStream(socket.getOutputStream());
//必须相应HTTP协议格式数据,否则浏览器不认识消息
ps.println("HTTP/1.1 200 0k");
ps.println("Content-Type:text/html;charset=UTF-8");
ps.println();//必须发送一个空行
//才可以响应数据回去给浏览器
ps.println("<span style='color:red;font-size:90px'>最牛的1497</span>");
ps.close();
} catch (Exception e) {
System.out.println(socket.getRemoteSocketAddress()+"下线了!!!");
}
}
}

heimaJava-网络编程的更多相关文章

  1. 猫哥网络编程系列:HTTP PEM 万能调试法

    注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...

  2. python select网络编程详细介绍

    刚看了反应堆模式的原理,特意复习了socket编程,本文主要介绍python的基本socket使用和select使用,主要用于了解socket通信过程 一.socket模块 socket - Low- ...

  3. Linux Socket 网络编程

    Linux下的网络编程指的是socket套接字编程,入门比较简单.在学校里学过一些皮毛,平时就是自学玩,没有见识过真正的socket编程大程序,比较遗憾.总感觉每次看的时候都有收获,但是每次看完了之后 ...

  4. 猫哥网络编程系列:详解 BAT 面试题

    从产品上线前的接口开发和调试,到上线后的 bug 定位.性能优化,网络编程知识贯穿着一个互联网产品的整个生命周期.不论你是前后端的开发岗位,还是 SQA.运维等其他技术岗位,掌握网络编程知识均是岗位的 ...

  5. 浅谈C#网络编程(一)

    阅读目录: 基础 Socket编程 多线程并发 阻塞式同步IO 基础 在现今软件开发中,网络编程是非常重要的一部分,本文简要介绍下网络编程的概念和实践. Socket是一种网络编程接口,它是对传输层T ...

  6. C++11网络编程

    Handy是一个简洁优雅的C++11网络库,适用于linux与Mac平台.十行代码即可完成一个完整的网络服务器. 下面是echo服务器的代码: #include <handy/handy.h&g ...

  7. Java - 网络编程

    Java的网络编程学习,关于计算机基础的学习参考:计算机网络基础学习 - sqh.     参考:  

  8. Linux网络编程-IO复用技术

    IO复用是Linux中的IO模型之一,IO复用就是进程预先告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程进程处理,从而不会在单个IO上阻塞了.Linux中,提 ...

  9. Python Socket 网络编程

    Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...

  10. iOS网络编程

    今天的重点是UIWebView.NSURLSession.JSon. 网络编程联网准备:1.在Info.plist中添加AppTransportSecurity类型Dictionary:2.在AppT ...

随机推荐

  1. 关于给widget添加属性

    在django中,我们通过修改Form/ModelForm的初始化函数__init__修改表单的显示样式,其中修改widget的属性操作和字典操作一致. 1.给widget添加属性 说明:这是在不影响 ...

  2. 修复右键批量打印PDF文件的功能

    bat文件内容如下, 直接右键管理员运行即可. @echo off rem "功能描述:修复右键批量打印PDF文件的功能" rem "制作人:赵龙" rem & ...

  3. c函数调用过程

    一.内存结构内存大致可以分为四个部分:代码段,静态存储区,堆,栈.具体划分如下图所示: 栈:在执行函数时,函数内部局部变量的存储单元都可以在栈上创建,函数执行结束后会自动释放内存.栈内存的分配运算内置 ...

  4. 通过xshell在linux上安装nginx1.12.0

    0)环境安装 Nginx是C语言开发,建议在 Linux 上运行,当然,也可以安装 Windows 版本,本篇则使用 CentOS 7 作为安装环境. 0.1 gcc 安装 安装 nginx 需要先将 ...

  5. wamp+phpstrom+Xdebuge helper(google)

    一.软件安装两个软件的安装和第三个浏览器插件就不再赘述,网上有很多详细的教程,自行百度. 二.配置步骤1.wampwamp的优势在于自带xdebuge的dll文件,所以不需要在官网根据版本下载,具体位 ...

  6. ubuntu18 build opencv4 from source

    1 安装依赖 ## Install dependencies sudo apt -y install build-essential checkinstall cmake pkg-config yas ...

  7. drf从入门到飞升仙界 09

    接口文档 # 1.前后端分离 - 后端:写接口 - 前端:根据接口写app,小程序,pc端 # 2.作为后端开发 - 我们应该清楚: ---> /api/v1/login/ ---> 登录 ...

  8. window stm32 mcu 调试

    1.ARM内核的MCU开发和调试 1.通过keil + jlink(segger) 进行调试 2.通过arm-gdb+openocd+jlink调试 3.通过jtag 进行调试(电路不复杂,硬件只需要 ...

  9. vue仿QQ聊天室|vue聊天实例,直播聊天室

    图片压缩 百亿站点 基于vue2.0+vue-cli+vuex+vue-router+webpack+es6+wcPop等技术开发的仿微信聊天界面|仿微信聊天室vue-chatRoom,实现了微信聊天 ...

  10. 常见DOS命令及应用

    常见DOS命令使用 CMD打开方式 开始 + 系统 + 命令提示符 WIN键 + R 输入cmd + Enter WIN键 + R 输入cmd + Ctrl + Shift + Enter (管理员模 ...