把分布在不同地理区域的计算机专门的外部设备用通信线路互联成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息、共享硬件、软件、数据信息等资源
【4】TCP协议:可靠的
建立链接:三次握手
释放链接:四次挥手
InetAddress 和 InetScoketAddress【1】InetAddress 封装了IP
【2】InetScoketAddress 封装了IP ,端口号
InetAddress
public static void main(String[] args) throws UnknownHostException {
// InetAddress inetAddress = new InetAddress(); 不能直接创建对象,因为 InetAddress被default修饰了
InetAddress ia = InetAddress.getByName("192.169.199.222");
System.out.println(ia);
InetAddress localhost = InetAddress.getByName("localhost"); //指代的是本机的ip
System.out.println(localhost);
InetAddress ia2 = InetAddress.getByName("LAPTOP-0FIKEUU1"); //封装计算机名
System.out.println(ia2);
InetAddress ia3 = InetAddress.getByName("www.baidu.com"); //封装域名
System.out.println(ia3);
System.out.println(ia3.getHostName()); //获取域名
System.out.println(ia3.getHostAddress()); //获取ip地址
}
InetSocketAddress
public static void main(String[] args) {
//封装一个ip和端口号
InetSocketAddress isa = new InetSocketAddress("192.169.199.222",8080);
//得到域名
System.out.println(isa.getHostName());
//得到端口号
System.out.println(isa.getPort());
//getAddress 封装成一个 InetAddress对象
InetAddress ia = isa.getAddress();
}
网络通信的原理
套接字 - Socke
TCP 通信功能双向通信功能:模拟网站的登录,客户端输入账号密码,服务器端进行验证
功能:客户端发送一句话到服务器,服务器端相应一句话给客户端
客户端
public class TestClient {
public static void main(String[] args) throws IOException {
//1.创建套接字,指定服务器的IP和端口号
Socket s = new Socket("172.26.160.1",8888);
//2.利用输入流先服务端发送数据
OutputStream os = s.getOutputStream();
//OutputStream 没有发送字符串的方法,所有套了个DataOutputStream来处理流
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("你好");
//接收服务器端的回话
InputStream is = s.getInputStream();
DataInputStream dis = new DataInputStream(is);
System.out.println("服务器端对我说:"+dis.readUTF());
//3.关闭流 + 关闭网络资源
dos.close();
os.close();
s.close();
}
}
服务器
public class TestServer {
public static void main(String[] args) throws IOException {
//1.创建套接字,指定服务端和端口号
ServerSocket serverSocket = new ServerSocket(8888);
//2.等待客户端发来的信息
//accept阻塞方法:等待接收客户端的数据,什么是接收到数据了,什么是时候程序继续向下执行
Socket socket = serverSocket.accept();
// accept 的返回值是Socket,接到Socket以后,客户端和服务端就可以正常通信了
//3.感受到客户端
InputStream is = socket.getInputStream();
DataInputStream dis = new DataInputStream(is);
//4.读取客户端发来的数据,打印到控制台
System.out.println("客户端发来的数据为:"+dis.readUTF());
//向客户端发送一条数据 输出流
OutputStream os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("你好,我是服务器端,我收到了你的信息");
//5.关闭流
dis.close();
is.close();
socket.close();
serverSocket.close();
}
}
测试:
先开启服务器,在开启客户端
登录功能客户端发送账号密码,服务器端判断进行账号密码是否正确,返回给客户端信息,并加入异常处理机制
在User实体类中,要注意序列化问题!!
客户端
public class TestServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ObjectInputStream ois = null;
OutputStream os = null;
DataOutputStream dos = null;
try{
//1.创建套接字,指定服务端和端口号
serverSocket= new ServerSocket(8888);
//2.等待客户端发来的信息
//accept阻塞方法:等待接收客户端的数据,什么是接收到数据了,什么是时候程序继续向下执行
socket = serverSocket.accept();
// accept 的返回值是Socket,接到Socket以后,客户端和服务端就可以正常通信了
//3.感受到客户端
is = socket.getInputStream();
ois= new ObjectInputStream(is);
boolean flag = false;
//4.读取客户端发来的数据
User user = (User) ois.readObject();
if (user.getUsername().equals("admin") && user.getPassword().equals("123456")){
flag = true;
}
//向客户端输出结果
os = socket.getOutputStream();
dos = new DataOutputStream(os);
dos.writeBoolean(flag);
}catch (Exception e){
e.printStackTrace();
}finally {
//5.关闭流
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务器
public class TestServer {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//1.创建套接字,指定服务端和端口号
ServerSocket serverSocket = new ServerSocket(8888);
//2.等待客户端发来的信息
//accept阻塞方法:等待接收客户端的数据,什么是接收到数据了,什么是时候程序继续向下执行
Socket socket = serverSocket.accept();
// accept 的返回值是Socket,接到Socket以后,客户端和服务端就可以正常通信了
//3.感受到客户端
InputStream is = socket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
boolean flag = false;
//4.读取客户端发来的数据
User user = (User) ois.readObject();
if (user.getUsername().equals("admin") && user.getPassword().equals("123456")){
flag = true;
}
//向客户端输出结果
OutputStream os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeBoolean(flag);
//5.关闭流
ois.close();
is.close();
socket.close();
serverSocket.close();
}
}
多线程接收用户请求
解决:服务器必须一直在监听,等待客户端的请求,客户端不需要更改代码。
服务器
public static void main(String[] args) {
System.out.println("服务器启动成功....");
ServerSocket serverSocket = null;
Socket socket = null;
int count = 0; //定义一个计数器,用来计算客户端的请求数量
try {
//1.创建套接字,指定服务端和端口号
serverSocket = new ServerSocket(8888);
//加入死循环,服务器一直监听客户端是否发送数据
while (true) {
//accept阻塞方法:等待接收客户端的数据,什么是接收到数据了,什么是时候程序继续向下执行
socket = serverSocket.accept();
new ServerThread(socket).start();
count ++;
//获取当前用户的ip地址
System.out.println("当前是第:"+count+"个用户访问服务器,对应的用户是:"+ socket.getInetAddress().toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
多线程
//处理客户端的请求
public class ServerThread extends Thread{
Socket socket = null;
InputStream is = null;
ObjectInputStream ois = null;
OutputStream os = null;
DataOutputStream dos = null;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
//3.感受到客户端
is = socket.getInputStream();
ois= new ObjectInputStream(is);
boolean flag = false;
//4.读取客户端发来的数据
User user = (User) ois.readObject();
if (user.getUsername().equals("admin") && user.getPassword().equals("123456")){
flag = true;
}
//向客户端输出结果
os = socket.getOutputStream();
dos = new DataOutputStream(os);
dos.writeBoolean(flag);
}catch (Exception e){
e.printStackTrace();
}finally {
//5.关闭流
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
UDP通信
TCP
客户端:Socket 使用流:输出流
服务器端:ServerSocket 使用流:输入流
UDP:
发送方:DatagramSocket 发送:数据包 DatagramPacket
接收方:DatagramSocket 发送:数据包 DatagramPacket
UDP单项通信发送方:学生
接收方:老师
功能:学生对老师说一句话
发送方
//发送方
public class TestSend {
public static void main(String[] args) throws IOException {
System.out.println("学生上线...");
// 1.准备套接字,指定发送方的套接字
DatagramSocket ds = new DatagramSocket(8888);
//2.准备数据包
String str = "你好,老师";
byte[] bytes = str.getBytes();
/*
需要准备四个参数
1.所要发送的字符串数组
2.所要发送的字符串数组的长度
3.接收方的ip
4.接收方的端口号
*/
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"), 9999);
//发送
ds.send(dp);
//关闭流
ds.close();
}
}
接收方
//接收方
public class TestReceive {
public static void main(String[] args) throws IOException {
System.out.println("老师上线了....");
//1.创建套接字,指定接收方端
DatagramSocket ds = new DatagramSocket(9999);
//2.创建一个空的数据包,然后放入我们dp数据包中填充
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
//3.接收方的数据包,然后放入我们的dp数据包中填充
ds.receive(dp);
//4.取出数据
byte[] data = dp.getData();
String s = new String(data,0,dp.getLength());//dp.getLength() 学生发的有效数据
System.out.println(s);
//5.关闭资源
ds.close();
}
}
UDP双向通信
解决问题:双向通信,异常处理,持续对话,下线提示
学生:发送方
//发送方
public class TestSend {
public static void main(String[] args) {
System.out.println("学生上线...");
DatagramSocket ds = null;
try {
// 1.准备套接字,指定发送方的套接字
ds= new DatagramSocket(8888);
while (true){
//2.准备数据包,向老师发送信息
Scanner sc = new Scanner(System.in);
System.out.println("学生(bye,结束标识):");
String str = sc.next();
byte[] bytes = str.getBytes();
/*
需要准备四个参数
1.所要发送的字符串数组
2.所要发送的字符串数组的长度
3.接收方的ip
4.接收方的端口号
*/
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"), 9999);
//发送
ds.send(dp);
//判断学生的结束标识
if (str.equals("bye")){
break;
}
//创建一空数组,用来接收老师发送的数据
byte[] b = new byte[2048];
DatagramPacket dp2 = new DatagramPacket(b,b.length);
//取出老师发送的数据
ds.receive(dp2);
//接收老师信息
byte[] data = dp2.getData();
String s = new String(data,0,dp2.getLength());//dp.getLength() 有效数据
System.out.println("老师说:"+s);
}
}catch (SocketException e){
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
ds.close();
}
}
}
接收方:老师
//接收方
public class TestReceive {
public static void main(String[] args){
System.out.println("老师上线了....");
DatagramSocket ds = null;
try{
ds= new DatagramSocket(9999);
while (true){
//1.创建套接字,指定接收方端
//2.创建一个空的数据包,然后放入我们dp数据包中填充
byte[] bytes = new byte[2048];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
//3.接收方的数据包,然后放入我们的dp数据包中填充
ds.receive(dp);
//4.取出数据
byte[] data = dp.getData();
String s = new String(data,0,dp.getLength());//dp.getLength() 学生发的有效数据
System.out.println("学生说:"+s);
//如果老师接收到学生的下线标志,就跳出循环
if (s.equals("bye")){
System.out.println("学生下线了,老师也下线了");
break;
}
//老师进行回复
Scanner sc = new Scanner(System.in);
System.out.println("老师:");
String str = sc.next();
byte[] bytes1 = str.getBytes();
/*
需要准备四个参数
1.所要发送的字符串数组
2.所要发送的字符串数组的长度
3.接收方的ip
4.接收方的端口号
*/
DatagramPacket dp2 = new DatagramPacket(bytes1, bytes1.length, InetAddress.getByName("localhost"), 8888);
//发送
ds.send(dp2);
}
}catch (SocketException e){
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//5.关闭资源
ds.close();
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)