0


网络编程中“TCP”编程——简单通信

前言

    计算机网络是指两台或多台计算机组成的网络,在同一个网络中,任意两台计算机都可以直接通信,因此所有计算机必须遵循同一种网络协议

常用协议

TCP/IP协议(TCP协议和IP协议):

    TCP协议时一种面向连接,可靠传输的协议;

    IP协议是一种分组交换传输的协议;

UDP协议:

    UDP协议是一种无连接,不可靠传输的协议;

基于TCP/IP协议的TCP编程

     在学习TCP编程时,我们最先要了解的就是Socket,那什么是Socket呢?在开发网络应用程序的时候一定会遇到Socket这个概念,Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据传输到网络;

    使用Socket进行网络编程时,本质上是两个进程之间的网络通信,其中一个进程必须充当服务器端,它会主动监听某个指定的端口,另一个进程必须充当客户端,而客户端必须主动连接服务器的IP地址和指定端口,如果连接成功,服务器端就会与客户端成功的建立一个TCP连接,双方后续就可以随时发送和接收数据

    当Socket连接成功在服务器端和客户端之间建立之后:

对于服务器端来说,他是Socket指定的IP地址和指定的端口号;

对于客户端来说,他的Socket是它所在计算机IP地址和一个由操作系统分配的随机端口号;

服务器端:

要使用TCP编程,我们首先要编写服务器端程序,Java标准库提供了java.net.ServerSocket来实现对指定IP和指定端口的监听,ServerSocket的构造方法如下:

ServerSocket server = new ServerSocket(5237);

5237:自定义端口号;这里我们没有指定IP地址,表示在计算机的所有网络接口上进行监听。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Demo04 {
    public static void main(String[] args) {
        //ServerSocket:服务器端进行通信的对象
        try (ServerSocket server = new ServerSocket(5237)) {
            //死循环:不断接受客户端的连接
            while (true) {
                //服务器进入“等待”状态
                //如果有客户端连接,该方法返回客户的Socket
                Socket client=server.accept();
                InetAddress clientAdress=client.getInetAddress();
                System.out.println("客户端"+clientAdress.getHostAddress()+"开始连接......");
                //接受来自客户端上传的图片
                //输入流:读取来自客户端发送的图片文件流
                //输出端:写入本地图片
                String imgName=clientAdress.getHostName()+".jpg";
                try(InputStream in=client.getInputStream();
                        BufferedInputStream bis=new BufferedInputStream(in);
                        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("D:\\琐碎\\ServerImg\\"+imgName))){    
                    //每次读取来自客户端的图片文件流
                    //写入本地
                    byte[] buff=new byte[1024];
                    int len=-1;
                    while((len=bis.read(buff))!=-1) {
                        bos.write(buff, 0, len);
                    }
                    System.out.println("图片读取结束");
                    //输出提示信息=>客户端
                    try(BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));){
                        writer.write("upLoad Success!!!");
                        writer.newLine();
                    }
                    
                }
            }
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
     如果ServerSocket监听成功,我们就使用一个死循环来处理客户端的连接,以上代码中server.accept()表示每当有新的客户端连接,就返回一个Socket实例,这个Socket对象就是用来和刚连接的客户端进行通信的;

    如果没有客户端连接进来,accept()方法就会阻塞并一直等待。如果有多个客户端同时连接进来,ServerSocket会把连接添加到队列里,然后逐个进行处理。对于Java程序而言,只需要通过循环不断调用accept()就可以连续获取新的连接。

客户端:

相比服务器端,客户端程序就要简单很多。一个典型的客户端程序如下:

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class Demo03 {
    public static void main(String[] args) {
        //客户端
        //Socket:客户端进行通信的组件
        //本地图片读取 => 通过输出流(发送)至服务器
        //OutputStream:输出流,将读取到的本地图片文件流。发送(输出)至服务器
        //BufferedInputStream:输入流,读取本地图片
        try (Socket socket = new Socket("192.168.254.***",5237);
                OutputStream out=socket.getOutputStream();
                BufferedInputStream in=new BufferedInputStream(
                        new FileInputStream("D:\\琐碎\\20220220101644.jpg"));) {
            //每次读取1024个字节
            byte[] buff=new byte[1024];
            int len=-1;
            while((len=in.read(buff))!=-1) {
                //将读取到的内容,通过输出流发送至服务器
                out.write(buff);
            }
            //“输出”暂时结束(Socket没有关闭)
            socket.shutdownOutput();
            
            //读取来自服务器的反馈
            try(BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()))){
                String s=reader.readLine();
                System.out.println(s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
     当Socket连接创建成功后,无论是服务器端,还是客户端,我们都使用Socket实例进行网络通信。因为TCP是一种基于流的协议,因此,Java标准库使用InputStream和OutputStream来封装Socket的数据流,这样我们使用Socket的流,和普通IO流类似;

 写入网络数据时,必须要调用flush()方法。如果不调用flush(),就会出现客户端和服务器都收不到数据的情况,这并不是Java标准库的设计问题,而是我们以流的形式写入数据的时候,并不是一写入就立刻发送到网络,而是先写入内存缓冲区,直到缓冲区满了以后,才会一次性真正发送到网络,这样设计的目的是为了提高传输效率。如果缓冲区的数据很少,而我们又想强制把这些数据发送到网络,就必须调用flush()强制把缓冲区数据发送出去

.

标签: java eclipse

本文转载自: https://blog.csdn.net/w259149/article/details/125831734
版权归原作者 雾远望 所有, 如有侵权,请联系我们删除。

“网络编程中“TCP”编程——简单通信”的评论:

还没有评论