注:
- 网络编程(TCP/IP编程)!=网站编程
- 里面内容不做网络编程很难用到,如果需要时再看也可以,类似java的AWT和SWING编程
- 本文前半部分为马士兵课程中讲解内容,后半部分为疯狂java讲义中部分内容
一:网络基础
- 分层:应用–传输(udp/tcp)–网络(ip)–物理+数据链路
- 网络:tcp/ip详解
- ip协议:提供独一无二的ip地址
- udp/tcp协议:传输的方式
- tcp:可靠但是慢,先建立起连接才会继续进行,一定确保对方收到,也有序,先发的一定先到。例如银行取钱
- udp:说完就完事,不管对方的状态,不可靠但是快。例如qq聊天,游戏
二:TCP Socket(插座)编程
- 用来实现client–server的连接
- java.net包存有网络相关的类,包含Socket类和ServerSocket(TCP服务器端的插座,只用于实现TCP连接),因为UDP不分谁是server谁是client
- 端口号:用于表示是该ip上的,最多有65536个端口,最好用1024以上的端口,否则容易被系统占用,端口分为tcp端口和udp端口,每个都是65536个
- http默认端口80
三:TCP Socket通信
1.先起server再起client,server和client一起进行编写
package socket;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(6666);
while(true){
//accept和readline方法有点类似,为阻塞方法,如果没收到TCP请求 ,就会一直堵塞
Socket s = ss.accept();
//用于接收client发送的消息
DataInputStream dis = new DataInputStream(s.getInputStream());
//readUTF也是阻塞的,但是这种效率太低,因为如果一个client如果没法东西过来,就会一直卡住,后面的client也发不过来消息
System.out.println(dis.readUTF());
System.out.println("建立连接");
dis.close();
s.close();
}
}
}
package socket;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
//client端随机生成一个端口号,指定该端口用于连接本机的6666端口
Socket s = new Socket("127.0.0.1",6666);
//client利用输出流来与server端沟通
OutputStream os = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("hello server!");
dos.flush();
dos.close();
s.close();
}
}
四:UDP编程
因为未建立虚拟链路,所以严格意义上没有server和client的概念
package udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class TestUDPClient {
public static void main(String[] args) throws IOException {
byte[] buf = (new String("Hello").getBytes());
//DatagramPacket代表发送的数据报,被发送的地址在这里定义,而不是在Socket中定义
DatagramPacket dp = new DatagramPacket(buf, buf.length,new //代表Socket
InetSocketAddress("127.0.0.1",5678));
DatagramSocket ds = new DatagramSocket(9999);
ds.send(dp);
ds.close();
}
}
package udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class TestUDPServer {
public static void main(String[] args) throws IOException {
byte buf[] = new byte[1024];
//建立一个DatagramPacket用于接收client发来的数据
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//起一个数据包socket在UDP的5678端口上
DatagramSocket ds = new DatagramSocket(5678);
while(true){
//接收数据并放入DatagramPacket对象dp中,如果没收到内容,会阻塞
ds.receive(dp);
//dp.getLength():查看具体收了多少长度的数据
System.out.println(new String(buf,0,dp.getLength()));
}
}
}
17.1 网络编程的基础知识
- IP协议:提供网间连接的完善功能,允许数据传输,但不保证可靠性。
- TCP协议:保证数据传输可靠性
- IP协议传输数据时,将数据分割为一个个小包,而TCP协议会在通信的两个实体上各建立一个Socket,一端发送,另一端收集这些数据包,并正确还原其顺序,TCP使用重发机制,A给B传输数据时,当某数据包没收到B"确认收到"反馈时,TCP协议会要求A重新发送,这就是所谓的可靠性
- 主机名:bigserver,域名:mycompany.com,那么全限定域名:bigserver.mycompany.com
17.1.1 IP地址和端口号
- IP地址用于唯一地标识网络上的一个通信实体,端口号标识该通讯实体上的唯一一个通信程序
- IP地址为4组8位二进制数组成,中间用原点隔开。端口号为0-65535
17.2 Java的基本网络支持
17.2.1 使用InetAddress
- InetAddress代表IP地址
import java.io.IOException;
import java.net.InetAddress;
public class InetAddressTest {
public static void main(String[] args) throws IOException {
//1. 通过主机名获得InetAddress对象
InetAddress ip = InetAddress.getByName("www.baidu.com");
//2. 判断是否可达
System.out.println(ip.isReachable(2000));
//3. 获取IP字符串:43.243.169.21
System.out.println(ip.getHostAddress());
//4. 根据原始地址127.0.0.1,获取InetAddress对象
InetAddress local = InetAddress.getByAddress(new byte[]{127,0,0,1});
System.out.println(local.isReachable(2000));
//5.获取全限定域名(同时带有主机名和域名的名称):127.0.0.1
System.out.println(local.getCanonicalHostName());
//6.获取主机名
System.out.println(local.getHostName());
}
}
17.2.2 使用URLDecoder和URLEncoder
- URLDecoder和URLEncoder可以完成普通字符串与application/x-www-form-urlendcoded MIME字符串的相互转换
- 字符串中,西欧字符不转,转换中文字符时,首先看按哪种字符集进行转换,该字符集中如果一个中文占3个字节,由于每个字节又可以转换为2个16进制数,那么最终中文可以转为"%XX%XX%XX",X代表一个16进制数
- 当使用IE浏览器时,搜索中文,搜索栏中就会将中文转换成application/x-www-form-urlendcoded MIME字符串
import java.net.*;
public class URLDecoderTest {
public static void main(String[] args) throws Exception {
// 1. 将application/x-www-form-urlencoded字符串转换成普通字符串
// 其中的字符串是从IE浏览器复制过来的
String keyWord = URLDecoder.decode("%E7%96%AF%E7%8B%82java", "utf-8");
System.out.println(keyWord);
// 2. 将普通字符串转换成application/x-www-form-urlencoded字符串
String urlStr = URLEncoder.encode("疯狂Android讲义", "GBK");
System.out.println(urlStr);
}
}