zoukankan      html  css  js  c++  java
  • TCP和UDP套接字编程 (java实现)

    在了解网络编程之前,我们先了解一下什么叫套接字

    套接字即指同一台主机内应用层和运输层之间的接口

    由于这个套接字是建立在网络上建立网络应用的可编程接口

    因此也将套接字称为应用程序和网络之间的应用程序编程接口!

    关于TCP和UDP这里就不作太多介绍了,我们知道TCP是面向连接的,UDP是不面向连接的,TCP可靠,UDP不可靠即可!
    我们来设计一个应用来示范一下,流程:

    1. 客户机从键盘读取一行字符串,并通过套接字发送到服务器。
    2. 服务器从连接的套接字获取这行字符串,并对其进行修改(将小写转为大写),最后再发回客户端。
    3. 客户机读取到服务器发送的修改后的字符串,并输出到屏幕。

    不说太多了,直接上代码:

    TCP套接字编程:

     客户端:

    package TCP套接字编程;
    
    import java.io.BufferedReader;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    public class TCPClient {
        public static void main(String[] args) throws UnknownHostException,
                IOException {
            // 创建两个String类型的字符串用来接收和发送字符
            String sentence;
            String modifiedSentence;
    
            // 创建输入流,用来接收键盘输入
            BufferedReader inFromUser = new BufferedReader(new InputStreamReader(
                    System.in));
    
            // 创建一个Scoket型的clientScoket用来发起服务器和客户机之间的连接
            String postname = "169.264.187.20";// 客户端ip地址(请用自己电脑的ip地址代替)
            Socket clientSocket = new Socket(postname, 6789);
    
            // 创建向服务器发送信息的输出流
            DataOutputStream outToServer = new DataOutputStream(
                    clientSocket.getOutputStream());
    
            // 创建输入流,用来接收来自服务器的字节流
            BufferedReader inFromServer = new BufferedReader(new InputStreamReader(
                    clientSocket.getInputStream()));
    
            // 读取要发送的数据
            sentence = inFromUser.readLine();
    
            // 向服务器发送数据
            outToServer.writeBytes(sentence + '
    ');
    
            // 获取从服务器接收的数据
            modifiedSentence = inFromServer.readLine();
    
            // 打印接收数据
            System.out.println("From Server:" + modifiedSentence);
    
        }
    
    }

    服务器端:

    package TCP套接字编程;
    
    import java.io.BufferedReader;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServer {
        public static void main(String[] args) throws IOException {
            // 从客户端接收的字符串,要发送给客户端的字符串
            String clientSentence;
            String serverSentence;
    
            // 服务器打开6789端口,建立连接
            ServerSocket welcomeSocket = new ServerSocket(6789);
    
            while (true) {// 服务器的6789端口一直打开
    
                // 用此连接来获取和发送客户端数据流
                Socket connectionSocket = welcomeSocket.accept();
    
                // 获取来自客户端的数据流
                BufferedReader inFromClient = new BufferedReader(
                        new InputStreamReader(connectionSocket.getInputStream()));
    
                // 准备发送更改后的数据流
                DataOutputStream outToClient = new DataOutputStream(
                        connectionSocket.getOutputStream());
    
                // 读取收到的数据
                clientSentence = inFromClient.readLine();
    
                // 将读取到的数据都中的小写字母改为大写字母
                serverSentence = clientSentence.toUpperCase() + '
    ';
    
                // 发送修改后的数据给客户端
                outToClient.writeBytes(serverSentence);
    
            }
        }
    }

    UDP套接字编程:

    客户端:

    package UDP套接字编程;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    public class UDPClient {
        public static void main(String[] args) throws IOException {
            // 读取键盘输入的字节流
            BufferedReader inFromUser = new BufferedReader(new InputStreamReader(
                    System.in));
    
            // 为客户端创造一个传输信息的门,但是并没有像TCP那样建立连接
            DatagramSocket clientSocket = new DatagramSocket();
    
            // 调用DNS查询,得到主机名对应的IP地址
            InetAddress IPAddress = InetAddress.getByName(null);//null的话得到的是自己的IP地址
            System.out.println(IPAddress);
    
            // 定义需要发送的字节数组
            byte[] sendData = new byte[1024];// 不能动态开数组。。。
    
            // 定义需要接收的字节数组
            byte[] receiveData = new byte[1024];
    
            // 将从键盘接收到的数据先用字符串存起来
            String sentence = inFromUser.readLine();
    
            // 将字符串转为字节存入sendData
            sendData = sentence.getBytes();
    
            // 准备发送UDP数据报,里面包含发送内容和目的地址等信息
            DatagramPacket sendPacket = new DatagramPacket(sendData,
                    sendData.length, IPAddress, 9878);
    
            // 用这个门来发送数据报
            clientSocket.send(sendPacket);
    
            // 准备获取从服务器返回的数据报
            DatagramPacket receivePacket = new DatagramPacket(receiveData,
                    receiveData.length);
    
            // 用这个门来接收服务器发的数据报
            clientSocket.receive(receivePacket);
    
            // 将获取的数据报转换为String类型
            String modifiedSentence = new String(receivePacket.getData());
    
            // 打印从服务器收到的内容
            System.out.println("From Server:" + modifiedSentence + '
    ');
    
            // 关闭这个门
            clientSocket.close();
    
        }
    
    }

    服务器端:

    package UDP套接字编程;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    public class UDPServer {
        public static void main(String[] args) throws IOException {
    
            // 创建一个门,在9878端口
            DatagramSocket serverSocket = new DatagramSocket(9878);
    
            while (true) {
    
                // 定义接收数据的字节数组
                byte[] receiveData = new byte[1024];
    
                // 定义发送数据的字节数组
                byte[] sendData = new byte[1024];
    
                // 创建UDP数据报对象,准备接收UDP数据报
                DatagramPacket receivePacket = new DatagramPacket(receiveData,
                        receiveData.length);
    
                // 接收UDP数据报
                serverSocket.receive(receivePacket);
    
                // 将收到的UDP数据报转换为String字符串
                String sentence = new String(receivePacket.getData());
    
                // 得到接收到的UDP数据报的源IP地址
                InetAddress IPAddress = receivePacket.getAddress();
    
                // 得到接收到的UDP数据报的源端口号
                int port = receivePacket.getPort();
    
                // 小写字母全部变为大写字母
                String capitalized = sentence.toUpperCase();
    
                // 将字符串转换为字节数组以便发送
                sendData = capitalized.getBytes();
    
                // 准备发送字节数组,做好封装UDP数据报工作
                DatagramPacket sendPacket = new DatagramPacket(sendData,
                        sendData.length, IPAddress, port);
    
                // 通过门正式发送UDP数据报
                serverSocket.send(sendPacket);
    
            }
        }
    }

    分析:

    先运行服务器端代码,这样服务器才能工作:打开相应端口,做好接收数据的准备

    然后运行客户端代码,发送数据

    服务器工作时,对应端口一直的打开的,随时准备响应客户端的请求

    参考书籍:《计算机网络自顶向下方法》

  • 相关阅读:
    linux驱动开发学习一:创建一个字符设备
    如何高效的对有序数组去重
    找到缺失的第一个正整数
    .NET不可变集合已经正式发布
    中国人唯一不认可的成功——就是家庭的和睦,人生的平淡【转】
    自己动手搭建 MongoDB 环境,并建立一个 .NET HelloWorld 程序测试
    ASP.NET MVC 中如何用自定义 Handler 来处理来自 AJAX 请求的 HttpRequestValidationException 错误
    自己动手搭建 Redis 环境,并建立一个 .NET HelloWorld 程序测试
    ServiceStack 介绍
    一步一步实战扩展 ASP.NET Route,实现小写 URL、个性化 URL
  • 原文地址:https://www.cnblogs.com/yinbiao/p/10160574.html
Copyright © 2011-2022 走看看