- 网络编程
- 概念
- InetAddress类
- Socket(套接字)
- TCP通信
- 传输文件问题
- netstat指令
网络编程
概念
IP地址:是主机的唯一标识
- ip地址由网络地址+主机地址组成
- 分为ipv4和ipv6,ipv6是新的,可容纳的数量更多
- ipv4是4个字节,ipv6是16个字节
- ipv4分为a、b、c、d、e五类
- 查询ip地址指令,在命令行里输入ipconfig
域名:通过http协议将ip映射成域名,目的是为了方便记忆
端口:用于标识计算机上某个特定的网络程序
- 端口范围0-65535
- 0-1024已经被占用
- 常见的端口号http 80,tomcat 8080,mysql 3306
协议:协议就是一些规则,计算机之间进行通信需要遵守这些规则,如数据的格式(先写姓再写名,数据之间用逗号隔开)
协议是指计算机系统之间进行通信和数据交换所遵循的规则和约定。
这些规则和约定定义了数据传输的格式、顺序、错误检测和纠正等细节,以确保通信的可靠性和一致性。
TCP/IP模型有应用层,传输层,网络层,物理+数据链路层
传输层协议有TCP(传输控制协议),UDP(用户数据协议) 等
网络层协议有IP(因特网互联协议) 等
TCP协议
- 进行传输前,需要进行三次握手,来确认连接,所以是可靠的
- 在连接中,可传输大数据量的数据
- TCP协议进行通信的两个应用进程:客户端,服务器
- 效率低,因为每次传输前都要进行确认(三次握手)
- 传输完毕需要释放连接,不然其他人不能来建立通信
UDP协议
- 将数据,数据源,数据目的打包成一个数据包,直接发送,不需要建立连接,所以是不可靠的
- 数据的大小限制在64k以下
- 速度快,因为无需建立连接,且可以同时几个人向一个人通信
InetAddress类
InetAddress类用于表示IP地址,是用来获取和操作IP地址的类
- InetAddress.getlocalHost(),返回本机的InetAddress对象
- InetAddress.getbyname(String name),通过域名或主机名返回InetAddress对象
- getHostAddress(),返回InetAddress对象的ip地址
- getHostName(),返回InetAddress对象的名字
InetAddress localHost = InetAddress.getLocalHost(); //返回自己主机的对象
System.out.println(localHost);
InetAddress byName = InetAddress.getByName("www.baidu.com");//通过域名返回对象
System.out.println(byName);
System.out.println(byName.getHostName());//返回域名
System.out.println(byName.getHostAddress());//返回ip
Socket(套接字)
- 通信的两端都要有socket,是两台机器间通信的端点
- 网络通信其实就是socket间的通信
- socket允许程序把网络连接当成一个流,数据在两个socket间通过io传输
- 通过getOutputStream() 和 getInputStream()方法来通信
-
TCP通信
TCP通信分为客户端和服务器
客户端
通过创建socket来传输信息
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);//传输目标的ip和端口
然后返回outputstream来发送信息
OutputStream outputStream = socket.getOutputStream();
(注意:发送完信息后要写结束写出标记socket.shutdownOutput(),同理,输入完信息后要写结束下入标记socket.shutdownInput())
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello,world".getBytes());
socket.shutdownOutput();//关闭输出
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int datelength=0;
while((datelength=inputStream.read(bytes))!=-1){
System.out.println(new String(bytes,0,datelength));
}
socket.shutdownInput();
socket.close();
outputStream.close();
服务器端在自己本机上,需要放入监听的端口
通过ServerSocket来监听,监听到请求后返回socket对象来接收信息
ServerSocket serverSocket = new ServerSocket(9999);//创建服务器监听socket
然后通过返回一个socket实现通信
Socket accept = serverSocket.accept();//遇到请求后返回socket
然后返回inputstream来接收信息
InputStream inputStream = accept.getInputStream();
ServerSocket serverSocket = new ServerSocket(9999);//创建服务器监听socket
Socket accept = serverSocket.accept();//遇到请求后返回socket
System.out.println("服务器 接收到请求");
InputStream inputStream = accept.getInputStream();
byte[] bytes = new byte[1024];
int datelength=0;
while((datelength=inputStream.read(bytes))!=-1){
System.out.println(new String(bytes,0,datelength));
}
accept.shutdownInput();
OutputStream outputStream = accept.getOutputStream();
outputStream.write("hello,client".getBytes());
accept.shutdownOutput();
serverSocket.close();
accept.close();
inputStream.close();
socket的io流通信返回的是字节流,若要转成字符流,需用转换流来转换,最好再换为处理流,效率高
字符流输出完信息后,记得要用flush刷新
下述代码换为字符流实现:
服务器端
ServerSocket serverSocket = new ServerSocket(9999);
Socket accept = serverSocket.accept();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
String line="";
while ((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
accept.shutdownInput
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
bufferedWriter.write("server: hello,client");
bufferedWriter.flush();
accept.shutdownOutput();
accept.close();
bufferedReader.close();
客户端
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("client: hello server");
bufferedWriter.flush();
socket.shutdownOutput();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line="";
while ((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
socket.shutdownInput();
socket.close();
bufferedWriter.close();
传输文件问题
解决方法就是把要传输的文件转成字节数组,然后再输出
转成字节数组的方法需要自己写
若要把得到的字节数组再写成一个文件,就是用FileOutputstream(文件路径),然后write(这个字节数组),会自动创建这个文件
Serversocket是用来监听并构建连接,构建连接后直到close,都可以多次用socket通信
若要服务器返回数据到客户端,直接在accept.shutdownInput后,用接收数据的那个accept就行,每个socket都可以多次使用
服务器
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务器端等待接收");
Socket accept = serverSocket.accept();
BufferedInputStream bufferedInputStream = new BufferedInputStream(accept.getInputStream());
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("C:\\Users\\czy\\Desktop\\learnInformation\\image\\image222.png"));
byte[] bytes = SreamUtils.streamToByteArray(bufferedInputStream);//把要写入的文件转成字节数组,然后再写入
bufferedOutputStream.write(bytes);//写入这个字节数组
accept.shutdownInput();
//接收到之后传输信息给客户端
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
bufferedWriter.write("server:接收到了文件");
bufferedWriter.flush();//字符流传输后记得要刷新
accept.shutdownOutput();
//关闭
bufferedOutputStream.close();
bufferedInputStream.close();
accept.close();
serverSocket.close();
客户端
Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\czy\\Desktop\\learnInformation\\image\\image2.png"));
byte[] bytes = SreamUtils.streamToByteArray(bufferedInputStream);//把要输出的文件转成字节数组,然后再输出
bufferedOutputStream.write(bytes);//写入字节数组
socket.shutdownOutput();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line="";
while((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
socket.shutdownInput();
bufferedInputStream.close();
bufferedOutputStream.close();
socket.close();
netstat指令
- netstat -an该指令可以查看当前主机网络情况,包括端口监听情况和网络连接情况
- netstat -an|more可以分页显示
- netstat -anb|more可以更细致的看到是哪个程序在监听(需用管理员身份运行)
当客户端连接到服务器后,实际上客户端也是通过一个端口和服务器来通信的,这个端口由TCP/IP来分配