- 网络编程
- IP
/**
* IP:定位一个节点:计算机、路由、通讯设备等
* InetAddress:多个静态方法
* 1、getLocalHost 返回本机
* 2、getByName 根据域名DNS | IP地址 -->IP地址
* 两个成员方法:
* 1、getHostAddress 返回计算机地址
* 2、getHostName 返回计算机名
*
*/
public class IPTest {
public static void main(String[] args) throws UnknownHostException {
//使用getLocalHost方法创建InetAddress对象
InetAddress addr=InetAddress.getLocalHost();
System.out.println(addr.getHostAddress());
System.out.println(addr.getHostName());//输出计算机名
//根据域名得到InetAddress对象
addr=InetAddress.getByName("www.baidu.com");
System.out.println(addr.getHostAddress());//36.152.44.95
System.out.println(addr.getHostName());//输出计算机名
//根据ip得到InetAddress对象
addr=InetAddress.getByName("36.152.44.95");
System.out.println(addr.getHostAddress());
System.out.println(addr.getHostName());//输出的是IP而不是域名。因为这个IP地址不存在或DNS不允许进行IP地址和域名的映射,该方法就直接返回IP地址
}
}
- PORT
- 区分软件
- 2个字节,0~65535
- 不同协议端口之间不影响,同一个协议内端口不能重复
- 建议使用端口越大越好,1024以上的
/**
* 端口
* 1、区分软件
* 2、2个字节,0~65535
* 3、UDP TCP独立,同一个协议下端口不能冲突
* 4、定义端口 越大越好
* InetSocketAddress:父类SocketAddress
* 1、构造器
* new InetSocketAddress(“地址/域名”,端口)
* 2、方法
* getAddress
* getPort
* getHostName 一般通过getAddress获取
*
*/
public class PortTest {
public static void main(String[] args) {
//包含端口
InetSocketAddress socketAddress1=new InetSocketAddress("127.0.0.1",8080);
InetSocketAddress socketAddress2=new InetSocketAddress("localhost",9000);
System.out.println(socketAddress1.getHostName());
System.out.println(socketAddress2.getAddress());
System.out.println(socketAddress2.getPort());
}
}
- URL
基本用法
/**
* URL:统一资源定位器 互联网的三大基石之一(HTTP html),区分资源
* 1、协议
* 2、域名或计算机名
* 3、端口 http默认80
* 4、请求资源
* 例如:http://www.baidu.com:80/index.html?uname=user&age=18#a
*
*/
public class URLTest01 {
public static void main(String[] args) throws MalformedURLException {
URL url=new URL("http://www.baidu.com:80/index.html?uname=user&age=18#a");
//获取四个值
System.out.println("协议:"+url.getProtocol());
System.out.println("域名或IP:"+url.getHost());
System.out.println("端口:"+url.getPort());
System.out.println("请求资源:"+url.getFile());
System.out.println("请求资源:"+url.getPath());
//参数
System.out.println("参数:"+url.getQuery());
//锚点
System.out.println("锚点:"+url.getRef());
}
}
- 爬虫原理
1、URL
2、下载资源
3、分析资源—正则表达式
4、数据抽取 清洗 存储等
public class SpiderTest01 {
public static void test01() throws Exception {
// 获取URL
URL url = new URL("https://www.jd.com");
// 下载资源
InputStream is = url.openStream();
// 分析
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
BufferedWriter bw = new BufferedWriter(new FileWriter("jd.txt"));
String msg = null;
while ((msg = br.readLine()) != null) {
System.out.println(msg);
bw.write(msg);
bw.newLine();
}
bw.flush();
br.close();
// 处理……
}
// 模拟浏览器
public static void test02() throws Exception {
// 获取URL
URL url = new URL("https://www.dianping.com");
// 下载资源
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
//浏览器打开网址,F12获取
conn.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36");
// 分析
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
BufferedWriter bw = new BufferedWriter(new FileWriter("dianping.txt"));
String msg = null;
while ((msg = br.readLine()) != null) {
System.out.println(msg);
bw.write(msg);
bw.newLine();
}
bw.flush();
br.close();
// 处理……
}
public static void main(String[] args) throws Exception {
test02();
}
}
- 传输协议
传输层协议
1、TCP:面向连接、点到点通讯、高可靠性、占用系统资源多,效率低。应用:HTTP、ftp、smtp
2、UDP:非面向连接,传输不可靠,可能丢失、发送不管接受方是否准备好,也不管接收方是否收到、可以广播发送、开销小。应用:DNS、SNMP
应用层与传输层通过Socket通讯
- UDP编程
基本的流程:
发送方:
1、使用DatagramSocket 指定端口创建接收端
2、准备数据,一定转成字节数组
3、封装成DatagramPacket,需要指定目的地IP+PORT
4、发送包裹,send(DatagramPacket p)
5、释放资源
/**
* 发送端
* 1、使用DatagramSocket 指定端口创建接收端
* 2、准备数据,一定转成字节数组
* 3、封装成DatagramPacket,需要指定目的地IP+PORT
* 4、发送包裹,send(DatagramPacket p)
* 5、释放资源
*
*/
public class UDPClient {
public static void main(String[] args) throws IOException {
System.out.println("发送方启动中…………");
// 1、使用DatagramSocket 指定端口创建接收端
DatagramSocket client=new DatagramSocket(8888);
// 2、准备数据,一定转成字节数组
String data="努力学习!!!";
byte[] datas=data.getBytes();
// 3、封装成DatagramPacket,需要指定目的地IP+PORT
DatagramPacket packet=new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",9999));
// 4、发送包裹,send(DatagramPacket p)
client.send(packet);
// 5、释放资源
client.close();
}
}
接收方:
1、使用DatagramSocket 指定端口创建接收端
2、准备容器,封装成成DatagramPacket
3、阻塞式接收方法 receive(DatagramPacket p)
4、分析数据
byte[] getData()
int getLength()
5、释放资源
/**
* 接收端:
* 1、使用DatagramSocket 指定端口创建接收端
* 2、准备容器,封装成成DatagramPacket
* 3、阻塞式接收方法 receive(DatagramPacket p)
* 4、分析数据
* byte[] getData()
* int getLength()
* 5、释放资源
*
*/
public class UDPServer {
public static void main(String[] args) throws IOException {
System.out.println("接收端启动中…………");
//1、使用DatagramSocket 指定端口创建接收端
DatagramSocket server=new DatagramSocket(9999);
//2、准备容器,封装成成DatagramPacket
byte[] container=new byte[1024];//最大接收60k
DatagramPacket packet=new DatagramPacket(container,0,container.length);
//3、阻塞式接收方法 receive(DatagramPacket p)
server.receive(packet);//阻塞式
//4、分析数据
byte[] datas=packet.getData();
int len=packet.getLength();
System.out.println(new String(datas,0,len));
//5、释放资源
server.close();
}
}
与IO流对接:
只需改变发送方步骤中2,接收方步骤中4
1、基本类型:使用数据流 转成字节数组
2、引用类型:使用对象流 转成字节数组
3、文件:FileInput ByteArrayOutputStren 转成字节数组
应用:在线咨询系统:
TalkSend:
public class TalkSend implements Runnable {
private DatagramSocket client;
private BufferedReader reader;
private String toIP;
private int toPort;
public TalkSend(int port,String toIP,int toPort) {
this.toIP=toIP;
this.toPort=toPort;
try {
client = new DatagramSocket(port);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
String data;
try {
data = reader.readLine();
byte[] datas = data.getBytes();
// 3、封装成DatagramPacket,需要指定目的地IP+PORT
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length,
new InetSocketAddress(toIP, toPort));
// 4、发送包裹,send(DatagramPacket p)
client.send(packet);
if (data.equals("bye")) {
break;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 5、释放资源
client.close();
}
}
TalkReceive:
public class TalkReceive implements Runnable{
private DatagramSocket server;
private String from;
public TalkReceive(int port,String from) {
this.from=from;
try {
server=new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
// 2、准备容器,封装成成DatagramPacket
byte[] container = new byte[1024];// 最大接收60k
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
// 3、阻塞式接收方法 receive(DatagramPacket p)
try {
server.receive(packet);// 阻塞式
// 4、分析数据
byte[] datas = packet.getData();
int len = packet.getLength();
String data=new String(datas, 0, len);
System.out.println(from+":"+data);
if(data.equals("bye")) {
break;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//5、释放资源
server.close();
}
}
TalkTeacher :
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkReceive(9999,"学生")).start();//接收
new Thread(new TalkSend(5555,"localhost",8888)).start();//发送
}
}
TalkStudent :
public class TalkStudent {
public static void main(String[] args) {
new Thread(new TalkSend(6666,"localhost",9999)).start();//发送
new Thread(new TalkReceive(8888,"老师")).start();//接收
}
}
- TCP编程
- 基本流程
Clinet:
1、建立连接:使用Socket创建客户端+服务器地址端口
2、操作:输入输出流相关操作
3、释放资源
/**
* 熟悉流程
* 创建客户端
* 1、建立连接:使用Socket创建客户端+服务器地址端口
* 2、操作:输入输出流相关操作
* 3、释放资源
*
*/
public class Client {
public static void main(String[] args) throws IOException {
System.out.println("……………Client……………");
// 1、建立连接:使用Socket创建客户端+服务器地址端口
Socket client=new Socket("localhost",8888);
// 2、操作:输入输出流相关操作
DataOutputStream dos=new DataOutputStream(client.getOutputStream());
String data="hello";
dos.writeUTF(data);
dos.flush();
// 3、释放资源
dos.close();
client.close();
}
}
Server:
1、指定端口,使用ServerSocket
2、阻塞式等待连接accept
3、操作:输入输出流相关操作
4、释放资源
Server 在这里插入代码片
public class Server {
public static void main(String[] args) throws IOException {
System.out.println("……………Server……………");
// 1、指定端口,使用ServerSocket
ServerSocket server=new ServerSocket(8888);
// 2、阻塞式等待连接accept
Socket client=server.accept();
System.out.println("一个客户端建立了连接……");
// 3、操作:输入输出流相关操作
DataInputStream dis=new DataInputStream(client.getInputStream());
String data=dis.readUTF();
System.out.println(data);
// 4、释放资源
dis.close();
client.close();
}
}
- 与IO流对接-文件拷贝
FileServer
public class FileServer {
public static void main(String[] args) throws IOException {
System.out.println("……………Server……………");
// 1、指定端口,使用ServerSocket
ServerSocket server=new ServerSocket(8888);
// 2、阻塞式等待连接accept
Socket client=server.accept();
System.out.println("一个客户端建立了连接……");
// 3、操作:文件拷贝
InputStream is=new BufferedInputStream(client.getInputStream());
OutputStream os=new BufferedOutputStream(new FileOutputStream("IO-TCP.png"));
byte[] flush=new byte[1024];
int len=-1;
while((len=is.read(flush))!=-1) {
os.write(flush, 0, len);
}
os.flush();
// 4、释放资源
os.close();
is.close();
client.close();
}
}
FileClient
public class FileClient {
public static void main(String[] args) throws IOException {
System.out.println("……………Client……………");
// 1、建立连接:使用Socket创建客户端+服务器地址端口
Socket client=new Socket("localhost",8888);
// 2、操作:拷贝
InputStream is=new BufferedInputStream(new FileInputStream("src/IO.png"));
OutputStream os=new BufferedOutputStream(client.getOutputStream());
byte[] flush=new byte[1024];
int len=-1;
while((len=is.read(flush))!=-1) {
os.write(flush, 0, len);
}
os.flush();
// 3、释放资源
os.close();
is.close();
client.close();
}
}
- 模拟登录 多个客户端请求
LoginMultiClient
public class LoginMultiClient {
public static void main(String[] args) throws IOException {
System.out.println("……………Client……………");
// 1、建立连接:使用Socket创建客户端+服务器地址端口
Socket client = new Socket("localhost", 8888);
// 2、操作:输入输出流相关操作 先请求后响应
new Send(client).send();
// 接收
new Receive(client).receive();
// 3、释放资源
client.close();
}
static class Send {
private Socket client;
private DataOutputStream dos;
private BufferedReader console;
private String msg;
public Send(Socket client) {
console = new BufferedReader(new InputStreamReader(System.in));
this.msg = init();
this.client = client;
try {
dos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
try {
dos.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
private String init() {
try {
System.out.print("请输入用户名:");
String uname = console.readLine();
System.out.print("请输入密码:");
String upwd = console.readLine();
return "uname=" + uname + "&" + "upwd:" + upwd;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
public void send() {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
static class Receive {
private Socket client;
private DataInputStream dis;
public Receive(Socket client) {
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
try {
dis.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
public void receive() {
String result;
try {
result = dis.readUTF();
System.out.println(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
LoginMultiServer
public class LoginMultiServer {
public static void main(String[] args) throws IOException {
System.out.println("……………Server……………");
// 1、指定端口,使用ServerSocket
ServerSocket server = new ServerSocket(8888);
boolean isRunning = true;
// 2、阻塞式等待连接accept
while (isRunning) {
Socket client = server.accept();
System.out.println("一个客户端建立了连接……");
new Thread(new Channel(client)).start();
}
server.close();
}
//一个channel就代表一个客户端
static class Channel implements Runnable {
private Socket client;
// 输入流
private DataInputStream dis;
// 输出流
private DataOutputStream dos;
public Channel(Socket client) {
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
// 输出
dos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
release();
}
}
// 释放资源
private void release() {
try {
if (null != dos) {
dos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (null != dis) {
dis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (null != client) {
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 接收数据
private String receive() {
String datas = "";
try {
datas = dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
return datas;
}
// 发送数据
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
// 3、操作:输入输出流相关操作
String uname = "";
String upwd = "";
// 分析
String[] dataArray = receive().split("&");
for (String info : dataArray) {
String[] userInfo = info.split("=");
if (userInfo[0].equals("uname")) {
System.out.println("你的用户名为:" + userInfo[1]);
uname = userInfo[1];
} else if (userInfo[0].equals("upwd")) {
System.out.println("你的密码为:" + userInfo[1]);
upwd = userInfo[1];
}
}
if (uname.equals("study") && upwd.equals("123456")) {
send("登录成功,欢迎回来");
} else {// 失败
send("用户名或密码错误");
}
// 4、释放资源
release();
}
}
}
- 在线聊天室 封装版
Receive
/**
* 使用多线程封装了接收端
* 1、接收消息
* 2、释放资源
* 3、重写run
*
*/
public class Receive implements Runnable {
private DataInputStream dis;
private Socket client;
private boolean isRunning;
public Receive(Socket client) {
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
this.isRunning = true;
} catch (IOException e) {
System.out.println("Receive error");
release();
}
}
// 接收消息
private String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
System.out.println("Receive:receive error");
release();
}
return msg;
}
@Override
public void run() {
while(isRunning) {
String msg=receive();
if(!msg.equals("")) {
System.out.println(msg);
}
}
}
// 释放资源
private void release() {
this.isRunning = false;
StudyUtils.close(dis, client);
}
}
Send
/**
* 使用多线程封装了发送端
* 1、发送消息
* 2、从控制台获取消息
* 3、释放资源
* 4、重写run
*
*/
public class Send implements Runnable {
private BufferedReader console;
private DataOutputStream dos;
private Socket client;
private boolean isRunning;
public Send(Socket client) {
this.client = client;
console = new BufferedReader(new InputStreamReader(System.in));
try {
dos = new DataOutputStream(client.getOutputStream());
this.isRunning=true;
} catch (IOException e) {
System.out.println("Send error");
release();
}
}
@Override
public void run() {
while (isRunning) {
String msg = getStrFromConsole();
if (!msg.equals("")) {
send(msg);
}
}
}
// 发送消息
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("Send:send error");
release();
}
}
/**
* 从控制台获取消息
*
* @return
*/
private String getStrFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
// 释放资源
private void release() {
this.isRunning = false;
StudyUtils.close(dos, client);
}
}
TMultiClient
/**
* 在线聊天室:客户端
* 目标:封装 使用多线程实现多个客户可以正常收发多条信息
*
*/
public class TMultiClient {
public static void main(String[] args) throws Exception {
System.out.println("……………Client……………");
//1、建立连接:使用Socket创建客户端+服务的地址和端口
Socket client=new Socket("localhost",8888);
//2、客户端发送消息
new Thread(new Send(client)).start();
//3、客户端获取消息
new Thread(new Receive(client)).start();
}
}
TMultiChat
/**
* 在线聊天室:服务器
* 目标:封装 使用多线程实现多个客户可以正常收发多条信息
*
*
*/
public class TMultiChat {
public static void main(String[] args) throws IOException {
System.out.println("……………Server……………");
// 1、指定端口,使用ServerSocket
ServerSocket server = new ServerSocket(8888);
// 2、阻塞式等待连接accept
while (true) {
Socket client=server.accept();
System.out.println("一个客户端建立了连接");
new Thread(new Channel(client)).start();
}
}
//一个客户端代表一个channel
static class Channel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private Socket client;
private boolean isRunning;
public Channel(Socket client) {
this.client=client;
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
isRunning = true;
} catch (IOException e) {
release();
}
}
//接收消息
private String receive() {
String msg="";
try {
msg=dis.readUTF();
} catch (IOException e) {
System.out.println("receive error");
release();
}
return msg;
}
//发送消息
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("send error");
release();
}
}
//释放资源
private void release() {
this.isRunning=false;
StudyUtils.close(dis,dos,client);
}
@Override
public void run() {
while(isRunning) {
String msg=receive();
if(!msg.equals("")) {
send(msg);
}
}
}
}
}
- 在线聊天室 群聊+私聊
Receive
public class Receive implements Runnable {
private DataInputStream dis;
private Socket client;
private boolean isRunning;
public Receive(Socket client) {
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
this.isRunning = true;
} catch (IOException e) {
System.out.println("Receive error");
release();
}
}
// 接收消息
private String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
System.out.println("Receive:receive error");
release();
}
return msg;
}
@Override
public void run() {
while(isRunning) {
String msg=receive();
if(!msg.equals("")) {
System.out.println(msg);
}
}
}
// 释放资源
private void release() {
this.isRunning = false;
StudyUtils.close(dis, client);
}
}
Send
public class Send implements Runnable {
private BufferedReader console;
private DataOutputStream dos;
private Socket client;
private boolean isRunning;
private String name;
public Send(Socket client,String name) {
this.client = client;
console = new BufferedReader(new InputStreamReader(System.in));
this.isRunning=true;
this.name=name;
try {
dos = new DataOutputStream(client.getOutputStream());
//发送名称
send(name);
} catch (IOException e) {
System.out.println("Send error");
release();
}
}
@Override
public void run() {
while (isRunning) {
String msg = getStrFromConsole();
if (!msg.equals("")) {
send(msg);
}
}
}
// 发送消息
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("Send:send error");
release();
}
}
/**
* 从控制台获取消息
*
* @return
*/
private String getStrFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
e.printStackTrace();
System.out.println("getStrFromConsole error");
}
return "";
}
// 释放资源
private void release() {
this.isRunning = false;
StudyUtils.close(dos, client);
}
}
Chat
public class Chat {
private static CopyOnWriteArrayList<Channel> all = new CopyOnWriteArrayList<Channel>();
public static void main(String[] args) throws IOException {
System.out.println("……………Server……………");
// 1、指定端口,使用ServerSocket
ServerSocket server = new ServerSocket(8888);
// 2、阻塞式等待连接accept
while (true) {
Socket client = server.accept();
System.out.println("一个客户端建立了连接");
Channel c = new Channel(client);
all.add(c);// 管理所有的成员
new Thread(c).start();
}
}
// 一个客户端代表一个channel
static class Channel implements Runnable {
private DataInputStream dis;
private DataOutputStream dos;
private Socket client;
private boolean isRunning;
private String name;
public Channel(Socket client) {
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
isRunning = true;
// 获取名称
name = receive();
// 欢迎你的到来
this.send("欢迎你的到来");
sendOthers(this.name + "来到了Study聊天室", true);
} catch (IOException e) {
release();
}
}
// 接收消息
private String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
System.out.println("receive error");
release();
}
return msg;
}
// 发送消息
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("send error");
release();
}
}
/**
* 群聊 :获取自己的消息发给其他人
* 私聊:约定数据格式:@xxx:msg
* @param msg
*/
private void sendOthers(String msg,boolean isSys) {
boolean isPrivate=msg.startsWith("@");
if(isPrivate) {//私聊
//获取目标和数据
String data=msg.substring(1, msg.length());
String[] datas=data.split(":");
String targetName=datas[0];
msg=datas[1];
for(Channel other : all) {
if(other.name.equals(targetName)) {//目标
other.send("["+this.name+" 悄悄地说]"+msg);
break;
}
}
}else {//群聊 或系统消息
for (Channel other : all) {
if (other == this)
continue;
if(!isSys) {
other.send("["+this.name+"]"+msg);//群聊消息
}else {
other.send(msg);//系统消息
}
}
}
}
// 释放资源
private void release() {
this.isRunning = false;
StudyUtils.close(dis, dos, client);
// 退出
all.remove(this);
sendOthers(this.name + "离开了群聊……", true);
}
@Override
public void run() {
while (isRunning) {
String msg = receive();
if (!msg.equals("")) {
// send(msg);
sendOthers(msg, false);
}
}
}
}
}
Client
public class Client {
public static void main(String[] args) {
System.out.println("……………Client……………");
BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名:");
String name="";
try {
name = br.readLine();
} catch (IOException e) {
e.printStackTrace();
System.out.println("br.readLine error");
}
//1、建立连接:使用Socket创建客户端+服务的地址和端口
Socket client=null;
try {
client = new Socket("localhost",8888);
} catch (UnknownHostException e) {
e.printStackTrace();
System.out.println("new Socket error");
} catch (IOException e) {
e.printStackTrace();
System.out.println("new Socket error");
}
//2、客户端发送消息
new Thread(new Send(client,name)).start();
//3、客户端获取消息
new Thread(new Receive(client)).start();
}
}
StudyUtils
public class StudyUtils {
/**
* 释放资源
*/
public static void close(Closeable... targets) {
for(Closeable target:targets) {
try {
if(null!=target) {
target.close();
}
}catch(Exception e){
}
}
}
}
- 总结
1、定位:
如何定位一台机器?IP —>InetAddress
如何定位机器上的软件?PORT----->InetSocketAddress
如何定位软件上的资源?URL------->Url
2、底层传输协议:
TCP:面向连接,安全可靠,性能低,底层使用IO字节流
服务端:ServerSocket :accept()
客户端:Socket
UDP:非面向连接,性能高
发送/接收:DatagramSocket:send() reveive()
数据:DatagramPacket
基于以上协议可以做Socket编程,Socket是传输层与应用层的接口。