一、网络编程作用
1、通过网络编程,我们可以实现通过网络编程的程序访问其他的计算机实现资源共享和数据通信
2、我们要做的是实现两台计算机之间的通信:
需要先通过电脑的ip地址找到计算机,
然后通过应用程序的端口号找到需要通信的应用程序
然后按照某种协议发送数据
3、
- 本机的地址
通过dos命令行的ipconfig命令,可以获取本机的IP地址
package 网络连接三要素;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPSend {
public static void main(String[] args) throws Exception {
DatagramSocket ds=new DatagramSocket();
//创建数据包
// DatagramPacket(byte[] buf, int length, InetAddress address, int port)
// 构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
byte [] b="我是JAVA".getBytes();
int len=b.length;
InetAddress address=InetAddress.getByName("msn");
int port=10088;
DatagramPacket p=new DatagramPacket(b,len,address,port);
//发送数据
ds.send( p);
//关闭资源
ds.close();
}
}
package 网络连接三要素;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPRecieve {
//此版本出现的问题:使用的byte是1024kb,但是我们接收的的数据只有几个字符,所以解析时应该注意长度
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10088);
// 接收数据包
byte bys[] = new byte[1024];
DatagramPacket p = new DatagramPacket(bys, bys.length);
ds.receive(p);
// 解析数据包
// getData()
// 返回数据缓冲区
byte[] data = p.getData();
// String string = data.toString();
// 返回要发送的数据的长度或接收到的数据的长度
String string = new String(data, 0, p.getLength());
// 输出数据
System.out.println(string);
// 关闭客户端
ds.close();
}
}
package 网络连接三要素;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class TCPSend {
public static void main(String[] args) throws IOException {
Socket s = new Socket("192.168.2.138", 10010);
OutputStream os = s.getOutputStream();
os.write("我来了,TCP".getBytes());
s.close();
}
}
package 网络连接三要素;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPRecieve {
public static void main(String[] args) throws IOException {
ServerSocket s = new ServerSocket(10010);
Socket accept = s.accept();
InputStream is = accept.getInputStream();
byte[] b = new byte[1024];
int read = is.read(b);// 将数据读取到b中,并返回数组长度
String string = new String(b, 0, read);
System.out.println(string);
s.close();
}
}
写代码过程中遇到的问题
1、思路整理:
UDP协议:
- 首先,使用DatagramSocket创建一个无参客户端对象,
- 然后将数据打包,通过客户端对象的send方法发送,
- 最后关闭客户端对象。
其中,打包使用DatagramPacket类进行,这个类可以将字节数组的数据进行打包。打包使用的内容有:字节数组,字节数组的长度,以及服务器端的IP,也就是InetAddress对象,还有应用程序的端口号。 - 当服务端接收数据时,也是通过DatagramSocket对象,接收客户端发送的数据包,
- 然后将数据包中的内容解析,相当于一个解压缩的过程。
- 解析后通过数据包的getData方法会得到一个字节数组,对数据进行操作,比如说可以进行输出。
- 然后将服务端对象关闭。
那么接收客户端发来的数据通过的也是数据包DatagramPacket对象。这个对象需要有一个容器存放数据,也就是字节数组,还需要知道要读取的字节数。一般写的比较大,比如1024。然后通过服务端对象的recieve方法对数据包进行接收。
2、String问题
在解析客户端发来的数据时,会通过包的getData方法得到数据的字节数组。一般为了方便操作,比如输出方便,会将其转化为字符串类型。老师讲课使用的构造方法,我想为什么不适用toString().我转字符串类型时,想当然地使用的b.toString()方法,结果总是不对。后来经过查阅资料和思考,突然想起来平时我们输出一个类时会重写toString方法,然后我查看toString源码,发现跟输出结果相同。
所以,要实现此功能需要使用字符串的构造方法String s=new String(b);
3、TCP协议区分输入和输出流
对于客户端来说,input是服务端回写的时候使用,output是向服务端发送数据使用
对于服务端,input是服务端接受数据使用,output是服务端回写的时候使用
总结:不论是哪个端,有一方告诉你数据,那么你就需要读内容,读也就是输入,input。当要告诉其他方时,需要使用output
4、TCP理解对象构造方法
对于客户端,我们需要告知所需要访问的电脑和应用程序,所以参数使用两个
对于服务端,访问的电脑已经确定,需要确定的是端口号,因此参数是端口号
5、TCP输入输出流
ServiceSocket类中,是没有输入输出流相关方法的,它使用的是Socket对象的输入输出流,所以在服务端必须先通过accept()方法获取客户端的Socket对象。
InputStream的read方法只能读取字节数组,返回值是读取到的个数
另外,TCP都是对字节流进行操作
6、其他错误
ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2 JDWP exit error AGENT_ERROR_NO_JNI_ENV(183): [util.c:840]
参考的博客