一 客户端和服务器端通信的步骤
二 TCP通信的客户端网络编程
TCP协议是严格区分客户端和服务器端的
1. TCP通信的客户端
- 向服务器端发送连接请求
- 给服务器端发送数据
- 读取服务器端回写的数据
2. 在Java中,提供了java.net包下的Socket类来表示客户端。Socket也叫"套接字",包含了IP地址和端口号
3. Socket的构造方法
- public Socket(String host,int port) throws UnknownHostException, IOException
- 构造方法的参数:host表示服务器主机的名称或者IP地址,port表示服务器端的端口号
- 当执行Socket的构造方法创建Socket对象时,会通过三次握手去建立和服务器端的连接,如果连接失败,会抛出异常
4. 经常使用的成员方法
- public OutputStream getOutputStream() throws IOException :给这个Socket对象返回一个OutputStream用于向服务器端发送数据
- public InputStream getInputStream() throws IOException :给这个Socket对象返回一个InputStream用于读取服务器端回写的数据
- public void close() throws IOException 关闭这个Socket对象
5. TCP通信的客户端网络编程的实现步骤
- 创建一个客户端Socket对象,构造方法绑定服务器短的IP地址和端口号
- 调用Socket对象的getOutputStream()方法,获得网络字节输出流OutputStream对象
- 调用OutputStream对象的write()方法向服务器端发送数据
- 调用Socket对象的getInputStream()方法,获得网络字节输入流InputStream对象
- 调用InputStream对象的read()方法读取服务器端发送的回写数据
- 释放资源(调用Socket对象的close()方法)
6. 注意事项
- 客户端和服务器端进行通信的时候,必须使用Socket对象提供的网络流,不能使用自己创建的流对象
- 当我们创建客户端Socket对象的时候,就会使用提供的IP地址和端口号通过三次握手和服务器端建立连接,如果说服务器端没有启动,建立连接失败,就会抛出异常;如果服务器端已经启动并且成功建立连接,那么就可以进行通信了。
7. TCP通信的客户端网络编程的实现
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;public class TCPClient {public static void main(String[] args) throws UnknownHostException, IOException {String host="127.0.0.1";//服务器端IP地址int port=8888;//服务器端端口号//创建客户端Socket对象,绑定服务器端的IP地址和端口号Socket socket=new Socket(host, port);//使用Socket对象获取网络输出流OutputStream对象OutputStream os =socket.getOutputStream();//通过OutputStream对象的write()方法向服务器端发送数据os.write("你好,服务器".getBytes());//使用Socket对象获取网络输出流InputStream对象InputStream is =socket.getInputStream();//通过InputStream对象的read()方法读取服务器端回写的数据byte[] data=new byte[2014];int len=is.read(data);System.out.println("服务器端回写的数据:"+new String(data, 0, len));//释放资源socket.close();}
}
三 TCP通信的服务器端网络编程
TCP协议是严格区分客户端和服务器端的
1. TCP通信的服务器端
- 接收客户端的请求
- 读取客户端发送的数据
- 给客户端回写数据
2. 在Java中,提供了java.net包下的ServerSocket类来表示服务器端。ServerSocket也叫"服务器端套接字"
3. ServerSocket的构造方法
-
public ServerSocket(int port,int backlog,InetAddress bindAddr)throws IOException:创建绑定到指定端口号的ServerSocket对象
- 构造方法的参数:port表示向系统要指定的端口号
4. 经常使用的成员方法
-
public Socket accept() throws IOException 通过accept()方法监听来自客户端的请求,如果监听到来自客户端的请求,则返回客户端的Socket对象
- public void close() throws IOException 关闭这个ServerSocket对象
5. TCP通信的客户端网络编程的实现步骤
- 创建一个服务器端的ServerSocket对象,并向系统要一个指定的端口号
- 使用ServerSocket对象的accept()方法监听客户端的请求,如果监听到则返回客户端Socket对象
- 使用客户端Socket对象的getInputStream()方法,获得网络字节输入流InputStream对象
- 调用InputStream对象的read()方法读取客户端发送的数据
- 使用客户端Socket对象的getOutputStream()方法,获得网络字节输出流OutputStream对象
- 调用OutputStream对象的write()方法向客户端发送回写数据
- 释放资源(调用Socket对象的close()方法,调用ServerSocket对象的close()方法)
6. 注意事项
- 服务器端必须明确是哪个客户端发送的请求,使用accept()方法获取客户端的Socket对象
7. TCP通信的服务器端网络编程的实现
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;public class TCPServer {public static void main(String[] args) throws IOException {//创建一个服务器端的ServerSocket对象,并向系统要一个指定的端口号ServerSocket serverSocket=new ServerSocket(8888);//使用ServerSocket对象的accept()方法监听客户端的请求,如果监听到则返回客户端Socket对象Socket socket=serverSocket.accept();//使用客户端Socket对象的getInputStream()方法,获得网络字节输入流InputStream对象InputStream is=socket.getInputStream();//调用InputStream对象的read()方法读取客户端发送的数据byte[] data=new byte[2048];int len=is.read(data);System.out.println("接受到的客户端发送的数据:"+new String(data, 0, len));//使用客户端Socket对象的getOutputStream()方法,获得网络字节输出流OutputStream对象OutputStream os=socket.getOutputStream();//调用OutputStream对象的write()方法向客户端发送回写数据os.write("你好,客户端,我已成功接受数据".getBytes());socket.close();serverSocket.close();}
}
四 TCP通信的综合案例:文件上传的原理
1. 客户端实现
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;public class TCPClient {public static void main(String[] args) throws UnknownHostException, IOException {//创建本地字节输入流,并绑定数据源String filename="F:\\016.jpg";FileInputStream fis=new FileInputStream(filename);//创建客户端Socket对象,并绑定服务器端的IP地址和端口号Socket socket=new Socket("127.0.0.1", 8888);//获取Socket对象的OutputStream对象OutputStream os=socket.getOutputStream();byte[] bytes=new byte[1024];int len=0;while((len=fis.read(bytes))!=-1) {os.write(bytes,0,len);}socket.shutdownOutput();//获取Socket对象的InputStream对象InputStream is=socket.getInputStream();while((len=is.read(bytes))!=-1) {System.out.println("服务器端回写的数据是:"+new String(bytes, 0, len));}fis.close();socket.close();}
}
2. 服务器端实现
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;import com.donglijiedian.thisDemo.Date;public class TCPServer {public static void main(String[] args) throws IOException {//创建一个ServerSocket对象,并向系统要指定的端口号ServerSocket serverSocket = new ServerSocket(8888);while (true) {//通过accept方法对客户端进行监听,获取客户端SocketSocket socket=serverSocket.accept();Thread thread=new Thread(new Runnable() {@Overridepublic void run() {try {//获取客户端Socket对象的InputStreamInputStream is=socket.getInputStream();//判断文件是否存在File file=new File("F:\\photo");String filename="F:\\photo"+"\\"+(new Date())+".jpg";if (!file.exists()) {file.mkdir();}//创建本地输出流对象FileOutputStream fos=new FileOutputStream(filename);byte[] bytes=new byte[2014];int len=0;while((len=is.read(bytes))!=-1) {//向本地写文件fos.write(bytes,0,len);}//获取Socket对象的OutputStreamOutputStream os=socket.getOutputStream();//给客户端回写数据os.write("服务器端成功接受到数据:".getBytes());fos.close();socket.close();} catch (Exception e) {System.out.println(e);}}});thread.start();}}
}
五 模拟BS服务器
1. 客户端访问服务器端的流程
2. 服务器端的实现