java scoket 通信_Java Socket应用-通信是这样练成的

网络基础知识

两台计算机通过网络进行通讯,需要满足一些必然条件

两台主机需要唯一标识,用来表示它们的身份,它们所在位置

共同的语言:协议

相应的端口号:辨别一台主机的多个应用程序

TCP/IP是目前世界上应用最为广泛的协议

是以TCP和IP为基础的不同层次上多个协议的集合,也成TCP/IP协议族 或 TCP/IP协议栈

TCP:Transmission Control Protocol 传输控制协议

IP:Internet Protocol 互联网协议

TCP/IP五层模型

5、应用层:用户直接接触到的,HTTP超文本传输协议、FTP文件传输协议、SMTP简单邮件传递协议、Telnet远程登录服务

4、传输层:TCP/IP协议

3、网络层

2、数据链路层

1、物理层 :网线、网卡

ca43d394d7a9?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

五层模型

IP地址:为实现网络中不同计算机之间的通讯,每台机器都必须有一个唯一的标识。

IPV4:IP规范的第四个版本

端口:1、用于区分不同应用程序;2、端口号范围为065535,其中01023为系统所保留(像HTTP、FTP)

3、IP地址和端口号组成了所谓的Socket,Socket是网络上运行的程序之间双向通信链路的终结点,是TCP和UDP的基础。

4、http:80 ftp:21 telnet:23

Java中的网络支持

针对网络通信的不同层次,Java提供的网络功能有四大类:

1、InetAddress:用于标识网络上的硬件资源,表示互联网协议(IP)地址;

2、URL:统一资源定位符,通过URL可以直接读取或写入网络上的数据;

3、Sockets:使用TCP协议实现网络通信的Socket相关的类;

4、Datagram:使用UDP协议,将数据保存在数据报中,通过网络进行通讯。

InetAddress

import java.net.InetAddress;

import java.net.UnknownHostException;

import java.util.Arrays;

public class InetAddressTest {

public static void main(String[] args) throws UnknownHostException {

// 获取本机的InetAddress实例

InetAddress address = InetAddress.getLocalHost();

System.out.println("计算名:" + address.getHostName());

System.out.println("IP地址:" + address.getHostAddress());

byte[] bytes = address.getAddress();// 获取字节数组形式的IP地址

System.out.println("字节数组形式的IP:" + Arrays.toString(bytes));

System.out.println(address);// 直接输出InetAddress对象

// 根据机器名获取InetAddress实例

// InetAddress address2=InetAddress.getByName("laurenyang");

InetAddress address2 = InetAddress.getByName("1.1.1.10");

System.out.println("计算名:" + address2.getHostName());

System.out.println("IP地址:" + address2.getHostAddress());

}

}

URL(Uniform Resource Locator)

统一资源定位符,表示Internet上某一资源的地址;

URL由两部分组成:协议名称和资源名称,中间用冒号隔开;

在java.net包中,提供了URL类来表示URL。

import java.net.MalformedURLException;

import java.net.URL;

public class URLTest {

public static void main(String[] args) {

try {

// 创建一个URL实例

URL imooc = new URL("http://www.imooc.com");

// ?后面表示参数,#后面表示锚点

URL url = new URL(imooc, "/index.html?username=tom#test");

System.out.println("协议:" + url.getProtocol());

System.out.println("主机:" + url.getHost());

// 如果未指定端口号,则使用默认的端口号,此时getPort()方法返回值为-1

System.out.println("端口:" + url.getPort());

System.out.println("文件路径:" + url.getPath());

System.out.println("文件名:" + url.getFile());

System.out.println("相对路径:" + url.getRef());

System.out.println("查询字符串:" + url.getQuery());

} catch (MalformedURLException e) {

e.printStackTrace();

}

}

}

获取网络内容

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.MalformedURLException;

import java.net.URL;

/**

* 使用URL读取网页内容

*/

public class URLReadTest {

public static void main(String[] args) {

try {

// 创建一个URL实例

URL url = new URL("http://www.baidu.com");

// 通过URL的openStream方法获取URL对象所表示的资源的字节输入流

InputStream is = url.openStream();

// 将字节输入流转换为字符输入流

InputStreamReader isr = new InputStreamReader(is, "utf-8");

// 为字符输入流添加缓冲

BufferedReader br = new BufferedReader(isr);

String data = br.readLine();// 读取数据

while (data != null) {// 循环读取数据

System.out.println(data);// 输出数据

data = br.readLine(); // 一次读取一行

}

br.close();

isr.close();

is.close();

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

Socket通信

TCP协议是面向连接、可靠的、有序的,以字节流的方式发送数据

Java中基于TCP协议实现网络通信的类

客户端的Socket类

服务器端的ServerSocket类

ca43d394d7a9?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

实现网络通信的类

Socket通信实现步骤

1、创建ServerSocket和Socket

2、打开连接到Socket的输入/输出流

3、按照协议对Socket进行读/写操作

4、关闭输入输出流、关闭Socket

实现步骤

服务器端:

1、创建 ServerSocket 对象,绑定监听端口

2、通过 accept() 方法监听客户端请求

3、连接建立后,通过输入流读取客户端发送的请求信息

4、通过输出流向客户端发送响应信息

5、关闭相关资源

客户端:

1、创建Socket对象,指明需要连接的服务器的地址和端口号

2、连接建立后,通过输出流向服务器端发送请求信息

3、通过输入流获取服务器响应的信息

4、关闭相关资源

import java.io.IOException;

import java.net.InetAddress;

import java.net.ServerSocket;

import java.net.Socket;

/*

* 基于TCP协议的Socket通信,实现用户登陆

* 服务器端

*/

public class Server {

public static void main(String[] args) {

try {

// 1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口

ServerSocket serverSocket = new ServerSocket(8888);

Socket socket = null;

// 记录客户端的数量

int count = 0;

System.out.println("***服务器即将启动,等待客户端的连接***");

// 循环监听等待客户端的连接

while (true) {

// 调用accept()方法开始监听,等待客户端的连接

socket = serverSocket.accept();

// 创建一个新的线程

ServerThread serverThread = new ServerThread(socket);

serverThread.setPriority(4); // 设置线程的优先级,范围为[0-10],默认为5

// 启动线程

serverThread.start();

count++;// 统计客户端的数量

System.out.println("客户端的数量:" + count);

InetAddress address = socket.getInetAddress();

System.out.println("当前客户端的IP:" + address.getHostAddress());

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.PrintWriter;

import java.net.Socket;

import java.net.UnknownHostException;

/*

* 客户端

*/

public class Client {

public static void main(String[] args) {

try {

// 1.创建客户端Socket,指定服务器地址和端口

Socket socket = new Socket("localhost", 8888);

// 2.获取输出流,向服务器端发送信息

OutputStream os = socket.getOutputStream();// 字节输出流

PrintWriter pw = new PrintWriter(os);// 将输出流包装为打印流

pw.write("用户名:alice;密码:789");

pw.flush();

socket.shutdownOutput();// 关闭输出流

// 3.获取输入流,并读取服务器端的响应信息

InputStream is = socket.getInputStream();

BufferedReader br = new BufferedReader(new InputStreamReader(is));

String info = null;

while ((info = br.readLine()) != null) {

System.out.println("我是客户端,服务器说:" + info);

}

// 4.关闭资源

br.close();

is.close();

pw.close();

os.close();

socket.close();

} catch (UnknownHostException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.PrintWriter;

import java.net.Socket;

/*

* 服务器线程处理类

*/

public class ServerThread extends Thread {

// 和本线程相关的Socket

Socket socket = null;

public ServerThread(Socket socket) {

this.socket = socket;

}

// 线程执行的操作,响应客户端的请求

public void run() {

InputStream is = null;

InputStreamReader isr = null;

BufferedReader br = null;

OutputStream os = null;

PrintWriter pw = null;

try {

// 获取输入流,并读取客户端信息

is = socket.getInputStream();

isr = new InputStreamReader(is);

br = new BufferedReader(isr);

String info = null;

while ((info = br.readLine()) != null) {// 循环读取客户端的信息

System.out.println("我是服务器,客户端说:" + info);

}

socket.shutdownInput();// 关闭输入流

// 获取输出流,响应客户端的请求

os = socket.getOutputStream();

pw = new PrintWriter(os);

pw.write("欢迎您!");

pw.flush();// 调用flush()方法将缓冲输出

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} finally {

// 关闭资源

try {

if (pw != null)

pw.close();

if (os != null)

os.close();

if (br != null)

br.close();

if (isr != null)

isr.close();

if (is != null)

is.close();

if (socket != null)

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

UDP Socket编程

UDP协议(用户数据报协议)是无连接、不可靠的、传输无序的。

UDP进行数据传输时,首先需要将要传输的数据定义成数据报(Datagram),在数据报中指明数据所要达到Socket(主机地址和端口号),然后再将数据报发送出去。

Java相关操作类

DatagramPacket:表示数据报包

DatagramSocket:进行端到端通信的类

服务端实现步骤:

1、创建DatagramSocket,指定端口号

2、创建DatagramPacket

3、接收客户端发送的数据信息

4、读取数据

客户端实现步骤:

1、定义发送信息

2、创建DatagramPacket,包含将要发送的信息

3、创建DatgramSocket

4、发送数据

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

/*

* 服务器端,实现基于UDP的用户登陆

*/

public class UDPServer {

public static void main(String[] args) throws IOException {

/*

* 接收客户端发送的数据

*/

// 1.创建服务器端DatagramSocket,指定端口

DatagramSocket socket = new DatagramSocket(8800);

// 2.创建数据报,用于接收客户端发送的数据

byte[] data = new byte[1024];// 创建字节数组,指定接收的数据包的大小

DatagramPacket packet = new DatagramPacket(data, data.length);

// 3.接收客户端发送的数据

System.out.println("****服务器端已经启动,等待客户端发送数据");

socket.receive(packet);// 此方法在接收到数据报之前会一直阻塞

// 4.读取数据

String info = new String(data, 0, packet.getLength());

System.out.println("我是服务器,客户端说:" + info);

/*

* 向客户端响应数据

*/

// 1.定义客户端的地址、端口号、数据

InetAddress address = packet.getAddress();

int port = packet.getPort();

byte[] data2 = "欢迎您!".getBytes();

// 2.创建数据报,包含响应的数据信息

DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port);

// 3.响应客户端

socket.send(packet2);

// 4.关闭资源

socket.close();

}

}

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

/*

* 客户端

*/

public class UDPClient {

public static void main(String[] args) throws IOException {

/*

* 向服务器端发送数据

*/

// 1.定义服务器的地址、端口号、数据

InetAddress address = InetAddress.getByName("localhost");

int port = 8800;

byte[] data = "用户名:admin;密码:123".getBytes();

// 2.创建数据报,包含发送的数据信息

DatagramPacket packet = new DatagramPacket(data, data.length, address, port);

// 3.创建DatagramSocket对象

DatagramSocket socket = new DatagramSocket();

// 4.向服务器端发送数据报

socket.send(packet);

/*

* 接收服务器端响应的数据

*/

// 1.创建数据报,用于接收服务器端响应的数据

byte[] data2 = new byte[1024];

DatagramPacket packet2 = new DatagramPacket(data2, data2.length);

// 2.接收服务器响应的数据

socket.receive(packet2);

// 3.读取数据

String reply = new String(data2, 0, packet2.getLength());

System.out.println("我是客户端,服务器说:" + reply);

// 4.关闭资源

socket.close();

}

}

多线程的优先级:未设置优先级可能会导致运行时速度非常慢,可降低优先级

是否关闭输出流和输入流:对于同一个socket,如果关闭了输出流,则与该输出流关联的socket也会被关闭,所以一般不用关闭流,直接关闭socket即可。

综合练习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值