EduCoder Java语言之网络编程

第1关:Server端监听

Socket编程

两台机器建立一个双向的网络连接实现数据交换,这个双向链路的一端称为一个Socket。它使用TCP协议提供了两台计算机之间的通信机制,客户端程序创建一个套接字,并尝试连接服务器的套接字。

两台计算机之间使用套接字建立TCP连接的一般步骤:

  • 服务器实例化一个 ServerSocket 对象,表示通过服务器上的端口通信。
  • 服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,直到客户端连接到服务器上给定的端口。
  • 服务器正在等待时,一个客户端实例化一个 Socket 对象,指定服务器名称和端口号来请求连接。Socket 类的构造函数试图将客户端连接到指定的服务器和端口号。如果通信被建立,则在客户端创建一个 Socket 对象能够与服务器进行通信。
  • 在服务器端,accept() 方法返回服务器上一个新的 socket 引用,该 socket 连接到客户端的 socket。

Java针对Socket编程提供的类

ServerSocket类
服务器应用程序通过使用java.net.ServerSocket类以获取一个端口,并且侦听客户端请求。

该类中的主要方法:

方法含义
bind()将ServerSocket绑定到特定地址(IP 地址和端口号)
accept()侦听并接收到此套接字的连接
close()关闭此套接字

Socket类
java.net.Socket类是客户端和服务器用来互相沟通的套接字。客户端通过实例化获取一个Socket对象,而服务器则通过ServerSocket类的accept()方法的返回值获得一个 Socket 对象。

该类中的主要方法:

方法含义
connect()请求一个socket连接
getOutputStream()获得写socket的输出流
getInputStream()获得读socket的输入流
close()关闭此套接字

DatagramSocket类
DatagramSocket类实现了一个发送和接收数据报的socket,传输层协议使用UDP,不能保证数据报的可靠传输。DataGramSocket主要有send, receive和close三个方法。

该类中的主要方法:

方法含义
send()发送一个数据报
receive()接收一个数据报
close()关闭一个流

SocketAddress
SocketAddress提供了一个socket地址,不关心传输层协议。这是一个虚类,由子类来具体实现功能、绑定传输协议。它提供了一个不可变的对象,被socket用来绑定、连接或者返回数值。

InetSocketAddress
InetSocketAddress实现了IP地址的SocketAddress,也就是有IP地址和端口号表达Socket地址。如果不制定具体的IP地址和端口号,那么IP地址默认为本机地址,端口号随机选择一个。

代码

package step1;

import java.net.ServerSocket;
import java.net.Socket;

public class Server {
	public ServerSocket serverSocket;
	public Socket socket;
	public void start() {
		try {
			Client client = new Client();
			/********** Begin *********/
            serverSocket = new ServerSocket(6000);
            client.start();    //启动客户端
            socket = serverSocket.accept();
            serverSocket.close();
            socket.close();
			/********** End *********/
			client.stop();	//关闭客户端
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}
}

第2关:Client端消息发送

流的含义
流是一个抽象的概念。当Java程序需要从数据源读取数据时,会开启一个到数据源的流。数据源可以是文件,内存或者网络等。同样,当程序需要输出数 据到目的地时也一样会开启一个流,数据目的地也可以是文件、内存或者网络等。

流的目的
流的创建是为了更方便地处理数据的输入输出。

流的分类
流分为字节流和字符流。字节流也称为原始数据,需要用户读入后进行相应的编码转换。而字节流的实现是基于自动转换的,读取数据时会把数据按照JVM的默认编码自动转换成字符。

Java中I/O流与Socket的结合运用
Java中的字节流由InputStream和OutputStream处理,而字符流由Reader和Writer处理。Reader和Writer是Java后加入的处理类,目的是让数据的处理更加方便。

下面是一个客户端向服务器发送字符串Hello World的部分关键代码:

Socket socket=new Socket("127.0.0.1", 1000);
OutputStream outputStream=socket.getOutputStream();
outputStream.write("Hello World".getBytes());

上述Java代码完成了三件事:

  • 根据IP地址与端口与服务器进行连接。
  • 创建OutputStream类的对象outputStream,并得到Socket类的对象socket的输出流。
  • 利用对象outputStream向服务器发送字符串Hello World,利用getBytes()方法将字符串转化为字节数组以便向服务端传递信息。

不要随便关闭对象outputStream,否则会造成对象socket也被关闭。如果只是想关闭对象socket的输出流,使用对象socket的shutdownOutput()方法。

代码

package step2;

import java.io.OutputStream;
import java.net.Socket;

public class Client {
	private Socket socket;
	private OutputStream socketOutputStream;
	public void start() {
		try {
			socket = new Socket("localhost",6000);
			/********** Begin *********/
            socketOutputStream = socket.getOutputStream();
            socketOutputStream.write("I am Client!".getBytes());


			/********** End *********/
			socket.shutdownOutput();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}
	public void stop() {
		try{
			socket.close();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}
}

第3关:一次完整通信

Java中InputStream类与Socket的结合运用
下面是一个客户端接收服务器发送的消息的部分关键代码:

Socket socket=new Socket("127.0.0.1", 1000);
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1000];
int length = inputStream.read(bytes);
String string = new String(bytes, 0, length);
System.out.print("Client has recevied: " + string);
inputStream.close();

上述Java代码完成了三件事:

  • 根据IP地址与端口与服务器进行连接。
  • 使用InputStream类创建对象inputStream,并得到Socket类的对象socket的输入流。
  • 利用read()方法读取服务端发来的字节数组消息,并利用String类转化成字符串输出至显示器。

代码

package step3;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
	private Socket socket;
	private OutputStream socketOutputStream;
	private InputStream socketInputStream;
	public void relation() {
		try{
			/********** Begin *********/
            socketInputStream = socket.getInputStream();
            byte[] bytes = new byte[1000];
            int length = socketInputStream.read(bytes);
            String serverData = new String(bytes,0,length);
            System.out.print("Client has recevied: " + serverData);

			/********** End *********/
			socket.shutdownInput();
		}
		catch(IOException e) {
			e.printStackTrace();
		}
	}
	public void start() {
		try {
			socket = new Socket("localhost",6000);
			/********** Begin *********/

            socketOutputStream = socket.getOutputStream();
            socketOutputStream.write("I am Client!".getBytes());

			/********** End *********/
			socket.shutdownOutput();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}
	public void stop() {
		try {
			socket.close();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}
}

相关推荐
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页