网络基础知识
- 端口号1024以下的尽量不要使用(大多已被互联网厂商使用)
- 资源定位:
URL(Uniform Resource Locator) 统一资源定位器,他是一种具体的URI
URI(Uniform Resource Identifier) 统一资源标识符,用来唯一的标识一个资源
InetAddress类和InetSocketAddress类
/**
* InetAddress类的使用
* 没有封装端口
* @author L J
*/
public class InetDemo {
public static void main(String[] args) throws UnknownHostException {
//通过getLocalHost()方法创建InetAddress对象
InetAddress addr = InetAddress.getLocalHost();
System.out.println(addr.getHostAddress()); //本机IPv4地址:10.56.0.107
System.out.println(addr.getHostName()); //输出本机计算机名
//根据域名得到InetAddress对象
addr = InetAddress.getByName("www.baidu.com");
System.out.println(addr.getHostAddress()); //返回百度服务器的IP地址:180.97.33.107
System.out.println(addr.getHostName()); //www.baidu.com
//根据IP地址得到InetAddress对象
addr = InetAddress.getByName("180.97.33.107");
System.out.println(addr.getHostAddress()); //返回百度服务器的IP地址:180.97.33.107
System.out.println(addr.getHostName()); //180.97.33.107
}
}
/**
* InetSocketAddress类的使用
* 在InetAddress的基础上+端口
* @author L J
*/
public class InetDemo2 {
public static void main(String[] args) {
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 9999);
System.out.println(address.getHostName()); //127.0.0.1
System.out.println(address.getPort()); //9999
InetAddress addr = address.getAddress();
System.out.println(addr.getHostAddress()); //127.0.0.1
System.out.println(addr.getHostName()); //127.0.0.1
}
}
URL
组成:协议+资源所在的主机域名+端口号+资源文件
public class URLDemo {
public static void main(String[] args) throws MalformedURLException {
//绝对路径构建
URL url = new URL("http://www.baidu.com:80/index.html#a?username = root");
System.out.println("协议:" + url.getProtocol()); //http
System.out.println("域名:" + url.getHost()); //www.baidu.com
System.out.println("端口:" + url.getPort()); //80
System.out.println("资源:" + url.getFile()); // /index.html
System.out.println("相对路径:" + url.getPath()); // /index.html
System.out.println("锚点:" + url.getRef()); //a?username = root
//getQuery方法,如果存在锚点,返回null;不存在就返回参数
System.out.println("参数:" + url.getQuery()); //null,如果去掉#a,返回username = root
//相对路径构建
url = new URL("http://www.baidu.com:80/a/");
url = new URL(url, "b");
System.out.println(url.toString()); // http://www.baidu.com:80/a/b
}
}
/**
* 获取资源
* 爬虫第一步
* @author L J
*/
public class URLDemo2 {
public static void main(String[] args) throws IOException {
URL url = new URL("http://www.baidu.com");
/*获取资源网络流
InputStream is = url.openStream();
byte[] buf = new byte[1024];
int len = 0;
while(-1 != (len = is.read(buf))) {
System.out.println(new String(buf, 0 ,len));
}
is.close();
*/
BufferedReader br =
new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("F:/DB/baidu.html"), "UTF-8"));
String msg = null;
while((msg = br.readLine()) != null) {
bw.append(msg);
bw.newLine();
}
bw.flush();
bw.close();
br.close();
}
}
聊天室+私聊
发送数据线程:
/**
* 发送数据线程
* @author L J
*/
public class Send implements Runnable{
private BufferedReader console; //控制台输入流
private DataOutputStream dos; //输出流
private boolean isRunning = true; //线程是否存活
private String name; //昵称
public Send() {
console = new BufferedReader(new InputStreamReader(System.in));
}
public Send(Socket client, String name) {
this();
try {
dos = new DataOutputStream(client.getOutputStream());
this.name = name;
send(this.name);
} catch (IOException e) {
isRunning = false;
//关闭输出流和控制台输入流
CloseUtil.close(dos, console);
}
}
//从控制台读取数据
private String getMsgFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
//发送数据
public void send(String msg) {
try {
if(msg != null && !msg.equals("")) {
dos.writeUTF(msg);
dos.flush();
}
} catch (IOException e) {
isRunning = false;
//关闭输出流和控制台输入流
CloseUtil.close(dos, console);
}
}
/**
* 1、从控制台读取数据
* 2、发送数据
*/
@Override
public void run() {
while(isRunning) {
send(getMsgFromConsole());
}
}
}
接收数据线程:
/**
* 接收数据线程
* @author L J
*/
public class Receive implements Runnable{
private DataInputStream dis; //输入流
private boolean isRunning = true; //线程是否存活
public Receive() {
}
public Receive(Socket client) {
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
isRunning = false;
CloseUtil.close(dis);
}
}
/**
* 接收数据
* @return 接收到的数据
*/
public String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
isRunning = false;
CloseUtil.close(dis);
}
return msg;
}
@Override
public void run() {
while(isRunning) {
System.out.println(receive());
}
}
}
关闭流工具:
/**
* 关闭流工具类
* @author L J
*/
public class CloseUtil {
//关闭流
public static void close(Closeable ... io) {
for(Closeable temp : io) {
if(temp != null) {
try {
temp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
客户端:
/**
* 聊天客户端
* 1、写出数据:输出流
* 2、读取数据:输入流
*
* 输入与输出在同一个线程内,应该独立处理
*
* @author L J
*/
public class ChatClient {
public static void main(String[] args) throws IOException, IOException {
Socket client = new Socket("localhost", 9999);
System.out.println("请输入昵称:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String name = br.readLine();
if(name.equals("")) {
return;
}
//发送数据,一条独立的路径
new Thread(new Send(client, name)).start();
//接收数据,一条独立的路径
new Thread(new Receive(client)).start();
}
}
服务器端:
/**
* 聊天服务器
*
* @author L J
*/
public class ChatServer {
//管理道路
private List<MyChannel> all = new ArrayList<MyChannel>();
public static void main(String[] args) throws IOException {
new ChatServer().start();
}
public void start() throws IOException {
ServerSocket server = new ServerSocket(9999);
while(true) {
Socket client = server.accept();
MyChannel channel = new MyChannel(client);
all.add(channel); //统一管理所有的道路
new Thread(channel).start(); //一条道路
}
}
/**
* 一个客户端一条道路
* @author L J
*/
private class MyChannel implements Runnable {
// 输入流
private DataInputStream dis;
// 输出流
private DataOutputStream dos;
//昵称
private String name;
// 线程是否存活
private boolean isRunning = true;
// 一个客户端一条道路
public MyChannel(Socket client) {
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
this.name = dis.readUTF();
this.send("欢迎进入聊天室!");
sendToOthers(this.name + "加入了聊天室!", true);
} catch (IOException e) {
isRunning = false;
CloseUtil.close(dos, dis);
}
}
/**
* 接收数据
* @return 接收到的数据
*/
public String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
isRunning = false;
CloseUtil.close(dis);
all.remove(this); //将出错的道路移除
}
return msg;
}
/**
* 发送数据
*
* @param msg
*/
public void send(String msg) {
if (msg == null && msg.equals("")) {
return;
}
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
isRunning = false;
// 关闭输入输出流
CloseUtil.close(dos);
all.remove(this); //将出错的道路移除
}
}
/**
* 发送数据给其他客户端
*/
private void sendToOthers(String msg, boolean sys) {
//是否为私聊
if(msg.startsWith("@") && msg.indexOf(":") > -1) {//私聊
//获取昵称
String name = msg.substring(1, msg.indexOf(":"));
String content = msg.substring(msg.indexOf(":") + 1);
for(MyChannel theOne : all) {
if(theOne.name.equals(name)) {
theOne.send(this.name + ":" + content);
}
}
}else{//群聊
//遍历容器
for(MyChannel other : all) {
//不发送给自己
if(other == this) {
continue;
}else{
if(sys) {//系统信息
other.send("系统信息:" + msg);
}else{
//发送给其它客户端
other.send(this.name + ":" + msg);
}
}
}
}
}
/**
* 接收数据,并发送给其他客户端
*/
@Override
public void run() {
while(isRunning) {
sendToOthers(receive(), false);
}
}
}
}