Socket网络编程

网络基础知识

基本概念

网络编程:不需要依赖浏览器进行通讯.,例如QQ。

网页编程:浏览器与服务器之间的通讯。

计算机网络:指分布在不同地域的计算机,通过外部设备连接起来,实现了资源共享与数据传输的计算机系统。

DHCP:(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作, 主要有两个用途:给内部网络或网络服务供应商自动分配IP地址,给用户或者内部网络管理员作为对所有计算机作中央管理的手段,在RFC 2131中有详细的描述。
  在DHCP客户端手工释放IP地址命令为ipconfig /release;
  更新IP地址命令为ipconfig /renew。

OSI网络互联七层框架与TCP/IP协议族(栈)五层网络架构

OSI(Open System Interconnect),即开放式系统互联,一般叫做OSI参考模型。

OSI层

功能

数据单元

封装、解封装过程

(浏览网站为例)

比喻

(邮递服务为例)

TCP/IP协议族(栈)

应用层

Application Layer

文件传输,电子邮件,文件服务,虚拟终端

data

(数据)

生成请求头

解析请求头

经理:写好信件草稿

经理:阅读信件

HTTPHTTPSFTPTELNETDNS,SSH,TFTP,SMTP,SNMP,POP3

表示层

Presentation Layer

数据格式化,代码转换,数据加密,数据压缩

转换成为计算机可识别的ASCII码

转换成请求头

助理:修改错字或格式

助理:提醒经理有信,翻译内容

没有协议

会话层

Session Layer

解除或建立与别的接点的联系

产生相应的主机进程

秘书:找出收信人地址,写好信封

秘书:拆信,制作副本

没有协议

传输层

Transport Layer

提供端对端的接口

segment

(数据段)

加上相应的端口号信息

匹配端口号

司机:寄信

司机:取信

TCPUDP

四层交换机、也有工作在四层的路由器

网络层

Network Layer

为数据包选择路由

packet

(数据包)

加上IP地址

匹配IP地址

分拣工:分拣

分拣工:分拣

IP,ICMP,RIP,OSPF,BGP,IGMP

路由器、三层交换机

数据链路层

Data Link Layer

传输有地址的帧以及错误检测功能

frame

(数据帧)

加上MAC地址

匹配MAC地址

包装工:打包装箱

拆包工:开箱拆包

SLIP,CSLIP,PPP,ARP,RARP,MTU

网桥(现已很少使用)、以太网交换机(二层交换机)、网卡(其实网卡是一半工作在物理层,一半工作在数据链路层)

物理层

Physical Layer

以二进制数据形式在物理媒体上传输数据

bits

(比特流)

转成bit流信息

转换成为计算机可识别的ASCII码

搬运工:将货搬上车

搬运工:将货搬下车

ISO2110,IEEE802,IEEE802.2

中继器、集线器、双绞线、网线、网卡

计算机网络通讯三要素:IP地址、端口号、通讯协议

IP地址

IP地址用来标识计算机,本质由32位二进制位数组成,为方便记录,把IP地址分成了4段,每段8个二进制数据用十进制表示。范围:2^8 = 0~255

IP地址 = 网络地址 + 主机地址

IP地址的类别(总共5类,常用3类):

IP地址类别

A类地址

B类地址

C类地址

IP地址结构

一个网络地址 + 三个主机地址

两个网络地址 + 两个主机地址

三个网络地址 + 一个主机地址

IP地址范围

0.0.0.0-127.255.255.255

128.0.0.0-191.255.255.255

192.0.0.0-223.255.255.255

私有IP地址范围

10.0.0.0-10.255.255.255

172.16.0.0-172.31.255.255

192.168.0.0-192.168.255.255

保留地址范围

127.0.0.0~127.255.255.255

169.254.0.0~169.254.255.255

一个公共地址最大主机数

(主机号的各位不能同时为0,1))

16777214(2^24-2)

65534(2^16-2)

254(2^8-2)

默认子网掩码

255.0.0.0

255.255.0.0

255.255.255.0

用途

政府

学校、事业单位

端口号

端口号用来标识计算机的进程。端口号的范围:0-65535

从0到1023,为系统所保留。自定义端口建议选1024 到 65535。

win7防火墙怎么设定开放端口:

1. 【控制面板】 -> 【windows防火墙】 -> 左侧【高级设置】 -> 左侧【入站规则】 -> 右侧【新建规则】:

2. 选中【端口】点击下一步。

3. 选中【TCP】并选中【特定本地端口】在后面的输入框中输入端口号,点击下一步。

4. 选中【允许连接】点击下一步。

5. 选择规则应用的网络,默认是全部选中的,采用默认即可,点击下一步。

6. 为新建的规则起名并做相应的描述,点击完成。

7. 返回【高级设置】,左侧【入站规则】按出站规则的设置类似操作。

通讯协议:Udp协议、tcp协议

含义

连接机制&数据可靠性

数据量

效率

用例

UDP协议

User Datagram Protocol,用户数据报协议

无连接的不可靠的传输协议:每个数据报都是一个独立的信息,包括完整的源地址或目的地址,因此不需建立发送方和接收方的连接。数据报无序易丢失。不可靠。它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

每个数据报大小限制在64K

效率高

对讲机、QQ通讯、cs游戏、视频会议

TCP协议

Transfer Control Protocol,传输控制协议

面向连接的可靠的传输协议:socket之间通过三次握手机制连接,双向数据传输,双方都可以进行发送或接收操作。数据流可靠有序无差错,有特有的通道,以字节流方式发送数据。HTTP、FTP、Telnet等应用都需要这种可靠的通信通道

传输大数据量

效率低

打电话、QQ文件传输

URL类

java.net.URL

URL:统一资源定位符

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

例子:http://localhost:8080/myweb/test.html

http://:http协议。执行流程:在本地hosts文件(在C:\Windows\System32\drivers\etc\)找域名所对应ip,如果找不到,联网去网络运营商的DNS服务器找,找到后访问该ip地址对应的服务器。

localhost:本地域名。(外地域名如www.baidu.com)。

8080:软件监听端口,定位具体的一个软件。(Tomcat:8080;mysql:3306;oracle:1521;系统默认80,URL中可不写)

myweb:web应用的名称(根目录)。

test.html:web应用的资源。

与URI(统一资源标识符)和URN(统一资源名)的区别

URI 可以进一步分为定位器(URL)、名称(URN),或者二者兼具。

有访问机制的URI也是URL。

URI可以描述任何文件:本地的,互联网上的;URL描述互联网上的(???)

request.getRequestURL() 得到的是 scheme://host.domain:port/path/filename

request.getRequestURI() 得到的是 /path/filename

常用scheme:http、https、ftp(文件传输协议)、mailto、file(计算机上的文件)

URL类常用方法

import java.net.MalformedURLException;

import java.net.URL;

public class TestURL {

public static void main(String[] args) {

try {

// 构造方法

URL baidu = new URL("http://www.baidu.com"); // http://www.baidu.com(协议一定要带上,和InetAddress不一样

URL index = new URL(baidu, "/index?name=twx#test");// http://www.baidu.com/index?name=twx#test

// 获取URL的信息

System.out.println(index.getProtocol()); // 获取协议: http

System.out.println(index.getHost()); // 获取主机: www.baidu.com

System.out.println(index.getPort()); // 获取端口: -1(默认80端口返回值是-1)

System.out.println(index.getPath()); // 获取文件路径: /index

System.out.println(index.getFile()); // 获取文件名: /index?name=twx

System.out.println(index.getQuery()); // 获取查询字符串: name=twx

System.out.println(index.getRef()); // 获取锚点: test

} catch (MalformedURLException e) {

e.printStackTrace();

}

}

}

用 URL 类的 openStream() 或 openConnection() 方法获取页面源代码

package com.tongwx.network;

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.net.MalformedURLException;

import java.net.URL;

public class GetSource {

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

getSourceByCharacterStream();

getSourceByByteStream();

}

/**

 * 用字符流方式获取

 */

private static void getSourceByCharacterStream() throws IOException {

URL url = new URL("https://www.google.com");//协议一定要带上,这不是浏览器输地址!

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));//乱码未解决

BufferedWriter bufferedWriter = new BufferedWriter(

new OutputStreamWriter(new FileOutputStream("E:/google.html"), "utf-8"));//乱码未解决

String str;

while (null != (str = bufferedReader.readLine())) {

bufferedWriter.write(str);

}

bufferedReader.close();

bufferedWriter.close();

}

/**

 * 用字节流方式获取

 */

private static void getSourceByByteStream() throws MalformedURLException, IOException, FileNotFoundException {

URL url = new URL("https://www.baidu.com");//协议一定要带上,这不是浏览器输地址!

InputStream inputStream = url.openStream();//相当于url.openConnection().getInputStream();

FileOutputStream fileOutputStream = new FileOutputStream("E:/baidu.html");

byte[] bs = new byte[2048];

int length;

while (-1 != (length = inputStream.read(bs, 0, bs.length))) {

fileOutputStream.write(bs, 0, length);//https://www.google.com乱码未解决

}

inputStream.close();

fileOutputStream.close();

}

}

java发送http的get、post请求

package com.tongwx.littleutils;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.URL;

import java.net.URLConnection;

import java.util.List;

import java.util.Map;

public class HttpRequest {

public static void main(String[] args) {

        //发送 GET 请求

        String s=HttpRequest.sendGet("http://localhost:6144/Home/RequestString", "key=123&v=456");

        System.out.println(s);

        

        //发送 POST 请求

        String sr=HttpRequest.sendPost("http://localhost:6144/Home/RequestPostString", "key=123&v=456");

        System.out.println(sr);

    }

    /**

     * 向指定URL发送GET方法的请求

     *

     * @param url

     *            发送请求的URL

     * @param param

     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。

     * @return URL 所代表远程资源的响应结果

     */

    public static String sendGet(String url, String param) {

        String result = "";

        BufferedReader in = null;

        try {

            String urlNameString = url + "?" + param;

            URL realUrl = new URL(urlNameString);

            // 打开和URL之间的连接

            URLConnection connection = realUrl.openConnection();

            // 设置通用的请求属性

            connection.setRequestProperty("accept", "*/*");

            connection.setRequestProperty("connection", "Keep-Alive");

            connection.setRequestProperty("user-agent",

                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

            // 建立实际的连接

            connection.connect();

            // 获取所有响应头字段

            Map<String, List<String>> map = connection.getHeaderFields();

            // 遍历所有的响应头字段

            for (String key : map.keySet()) {

                System.out.println(key + "--->" + map.get(key));

            }

            // 定义 BufferedReader输入流来读取URL的响应

            in = new BufferedReader(new InputStreamReader(

                    connection.getInputStream()));

            String line;

            while ((line = in.readLine()) != null) {

                result += line;

            }

        } catch (Exception e) {

            System.out.println("发送GET请求出现异常!" + e);

            e.printStackTrace();

        }

        // 使用finally块来关闭输入流

        finally {

            try {

                if (in != null) {

                    in.close();

                }

            } catch (Exception e2) {

                e2.printStackTrace();

            }

        }

        return result;

    }

    /**

     * 向指定 URL 发送POST方法的请求

     *

     * @param url

     *            发送请求的 URL

     * @param param

     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。

     * @return 所代表远程资源的响应结果

     */

    public static String sendPost(String url, String param) {

        PrintWriter out = null;

        BufferedReader in = null;

        String result = "";

        try {

            URL realUrl = new URL(url);

            // 打开和URL之间的连接

            URLConnection conn = realUrl.openConnection();

            // 设置通用的请求属性

            conn.setRequestProperty("accept", "*/*");

            conn.setRequestProperty("connection", "Keep-Alive");

            conn.setRequestProperty("user-agent",

                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

            // 发送POST请求必须设置如下两行

            conn.setDoOutput(true);

            conn.setDoInput(true);

            // 获取URLConnection对象对应的输出流

            out = new PrintWriter(conn.getOutputStream());

            // 发送请求参数

            out.print(param);

            // flush输出流的缓冲

            out.flush();

            // 定义BufferedReader输入流来读取URL的响应

            in = new BufferedReader(

                    new InputStreamReader(conn.getInputStream()));

            String line;

            while ((line = in.readLine()) != null) {

                result += line;

            }

        } catch (Exception e) {

            System.out.println("发送 POST 请求出现异常!"+e);

            e.printStackTrace();

        }

        //使用finally块来关闭输出流、输入流

        finally{

            try{

                if(out!=null){

                    out.close();

                }

                if(in!=null){

                    in.close();

                }

            }

            catch(IOException ex){

                ex.printStackTrace();

            }

        }

        return result;

    }    

}

下载文件

import com.google.common.collect.Lists;
import com.tongwx.demo.util.Debug;
import lombok.AllArgsConstructor;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.List;

public class FileDownloaderApp {

    public static void main(String[] args) {
        List<String> urls = Lists.newArrayList(
                "https://v2.cn.vuejs.org/js/vue.js",
                "https://v2.cn.vuejs.org/js/vue.min.js"
        );
        for (String url : urls) {
            new Thread(new FileDownloader(url)).start();
        }
    }

    // 文件下载器
    @AllArgsConstructor
    static class FileDownloader implements Runnable {
        private final String fileURL;

        @Override
        public void run() {
            Debug.info("Downloading from " + fileURL);
            String fileBaseName = fileURL.substring(fileURL.lastIndexOf('/') + 1);
            try {
                URL url = new URL(fileURL);
                String localFileName = System.getProperty("java.io.tmpdir") + "/FileDownloaderApp-" + fileBaseName;
                Debug.info("Saving to: " + localFileName);
                downloadFile(url, new FileOutputStream(localFileName), 1024);
            } catch (Exception e) {
                e.printStackTrace();
            }
            Debug.info("Done downloading from " + fileURL);
        }

        // 从指定的URL下载文件,并将其保存到指定的输出流中
        private void downloadFile(URL url, OutputStream outputStream, int bufSize) throws IOException {
            // 建立HTTP连接
            final HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
            httpConn.setRequestMethod("GET");
            ReadableByteChannel inChannel = null;
            WritableByteChannel outChannel = null;
            try {
                // 获取HTTP响应码
                int responseCode = httpConn.getResponseCode();
                // HTTP响应非正常:响应码不为2开头
                if (2 != responseCode / 100) {
                    throw new IOException("Error: HTTP " + responseCode);
                }

                if (0 == httpConn.getContentLength()) {
                    Debug.info("Nothing to be downloaded " + fileURL);
                    return;
                }
                inChannel = Channels.newChannel(new BufferedInputStream(httpConn.getInputStream()));
                outChannel = Channels.newChannel(new BufferedOutputStream(outputStream));
                ByteBuffer buf = ByteBuffer.allocate(bufSize);
                while (-1 != inChannel.read(buf)) {
                    buf.flip();
                    outChannel.write(buf);
                    buf.clear();
                }
            } finally {
                // 关闭指定的Channel以及HttpURLConnection
                closeChannels(inChannel, outChannel);
                httpConn.disconnect();
            }
        }
    }

    public static void closeChannels(Closeable... closeable) {
        if (null == closeable) {
            return;
        }
        for (Closeable c : closeable) {
            if (null == c) {
                continue;
            }
            try {
                c.close();
            } catch (Exception ignored) {
            }
        }
    }
}

TCP编程(Socket)

什么是Socket

Socket(套接字)是连接运行在网络上的两个程序间的双向通讯的端点。

使用Socket进行网络通信的实现步骤

  1. 服务器端创建ServerSocket对象,绑定监听端口,通过accept()方法监听客户端请求。
  2. 客户端创建Socket对象,指明需要连接的服务器的地址和端口号,对象一生成就会自动发出连接请求。
  3. 连接一旦建立,服务器端将自动创建新Socket绑定新端口以与客户端通信,原Socket和原端口继续监听其他客户端请求。
  4. 两端打开连接到Socket的输入输出流,客户端通过输出流发出请求信息,通过输入流获取响应信息;服务器通过输入流读取请求信息,通过输出流发送响应信息。
  5. 通信完毕,关闭相关资源(输入输出流和Socket)。

Server

Client

建立服务端监听
serverSocket

等待并接收连接请求

接收请求后,创建连接socket

建立连接
←――――――→

创建连接socket
向服务端发送请求

开始通信

InputStream
OutputStream


←――――――→

InputStream
OutputStream

结束通信

关闭socket

关闭socket

案例:使用基于TCP协议的Socket通信

package com.tongwx.network;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.ServerSocket;

import java.net.Socket;

package com.tongwx.network;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.Socket;

public class TcpServer {

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

ServerSocket serverSocket = new ServerSocket(5000);

while (true) {

//监听客户端请求,一旦连接返回新socket对象

Socket socket = serverSocket.accept();

new ServerInputThread(socket).start();

new ServerOtuputThread(socket).start();

}

}

}

public class TcpClient {

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

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

new ClientOutputThread(socket).start();

new ClientInputThread(socket).start();

}

}

class ServerInputThread extends Thread {

private Socket socket;

public ServerInputThread(Socket socket) {

this.socket = socket;

}

@Override

public void run() {

try {

InputStream inputStream = socket.getInputStream();

byte[] bs = new byte[200];

int readLength;

while (true) {

readLength = inputStream.read(bs);

String message = new String(bs, 0, readLength);

System.out.println(message);

// //以下方式出错,不知为何

// byte[] bs = new byte[200];

// int realLength;

// while (-1 != (realLength = inputStream.read(bs, 0, bs.length))) {

// System.out.println(new String(bs, 0, realLength));

// }

if ("EXIT".equals(message.toUpperCase())) {

inputStream.close();

socket.close();

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

class ClientInputThread extends Thread {

private Socket socket;

public ClientInputThread(Socket socket) {

this.socket = socket;

}

@Override

public void run() {

try {

InputStream inputStream = socket.getInputStream();

byte[] bs = new byte[200];

int readLength;

while (true) {

readLength = inputStream.read(bs);

String message = new String(bs, 0, readLength);

System.out.println(message);

// //以下方式出错,不知为何

// byte[] bs = new byte[200];

// int realLength;

// while (-1 != (realLength = inputStream.read(bs, 0, bs.length))) {

// System.out.println(new String(bs, 0, realLength));

// }

if ("EXIT".equals(message.toUpperCase())) {

inputStream.close();

socket.close();

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

class ServerOtuputThread extends Thread {

private Socket socket;

public ServerOtuputThread(Socket socket) {

this.socket = socket;

}

@Override

public void run() {

try {

OutputStream outputStream = socket.getOutputStream();

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

while (true) {

String readLine = bufferedReader.readLine();

outputStream.write(readLine.getBytes());

if ("EXIT".equals(readLine.toUpperCase())) {

outputStream.close();

socket.close();

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

class ClientOutputThread extends Thread {

private Socket socket;

public ClientOutputThread(Socket socket) {

this.socket = socket;

}

@Override

public void run() {

try {

OutputStream outputStream = socket.getOutputStream();

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

while (true) {

String readLine = bufferedReader.readLine();

outputStream.write(readLine.getBytes());

if ("EXIT".equals(readLine.toUpperCase())) {

outputStream.close();

socket.close();

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

InetAddress类

java.net.InetAddress

InetAddress(IP地址类)常用方法(没有构造方法,用静态方法获取实例)

获取InetAddress实例

static InetAddress

getLocalHost()

获取本地的IP地址(InetAddress实例)。

static InetAddress

getByName(String host)

获取指定主机名的IP地址。如果提供IP地址字符串,则仅检查地址格式的有效性。

static InetAddress[]

getAllByName(String host)

获取指定域名的IP地址数组。

获取InetAddress实例的信息

String

getHostName()

获取此IP地址的主机名。

String

getHostAddress()

获取此IP地址的字符串形式。

byte[]

getAddress() 

获取此IP地址的字节数组形式。

代码示例

import java.net.InetAddress;

import java.net.UnknownHostException;

public class IPDemo {

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

// 获取IP地址(InetAddress实例)的方法

InetAddress localHost = InetAddress.getLocalHost();// 获取本机IP地址(InetAddress实例):TWX/192.168.183.1

InetAddress byName = InetAddress.getByName("TWX");// 根据主机名获取IP地址:TWX/192.168.183.1

InetAddress byName = InetAddress.getByName("www.baidu.com");//www.baidu.com/103.235.46.39(不要带协议,和URL不一样

InetAddress byAddress = InetAddress.getByName("192.168.183.123");// 检查IP地址字符串格式有效性:/192.168.183.123

InetAddress[] allByName = InetAddress.getAllByName("java.sun.com");// 根据域名获取IP地址数组:{java.sun.com/156.151.59.19}

// 获取IP地址(InetAddress实例)信息的方法

String hostName = InetAddress.getLocalHost().getHostName();// 获取本机IP地址主机名:TWX

String hostAddress = InetAddress.getLocalHost().getHostAddress();// 获取本机IP地址字符串:192.168.183.1

byte[] hostAddressBytes = InetAddress.getLocalHost().getAddress();// 获取本机IP地址的字节数组。

System.out.println(Arrays.toString(hostAddressBytes));// [-64, -88, -73, 1]

}

}

UDP编程(DataGram)

案例

package com.tongwx.network;

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

public class UdpClient2 {

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

//接收

DatagramSocket datagramSocket = new DatagramSocket(7000);

byte[] bs = new byte[1000];

DatagramPacket datagramPacket = new DatagramPacket(bs, 1000);

datagramSocket.receive(datagramPacket);

System.out.println(new String(bs, 0, datagramPacket.getLength()));

//回复

String reply = "一曲菱歌敌万金!";

datagramPacket = new DatagramPacket(reply.getBytes(), reply.getBytes().length, datagramPacket.getAddress(),

datagramPacket.getPort());//注意:str.length() 不一定等于 str.getBytes().length

datagramSocket.send(datagramPacket);

datagramSocket.close();

}

}

package com.tongwx.network;

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

public class UDPClient1 {

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

//发送

DatagramSocket datagramSocket = new DatagramSocket();

String message = "画眉深浅入时无?";

DatagramPacket datagramPacket = new DatagramPacket(message.getBytes(), message.getBytes().length,

InetAddress.getByName("localhost"), 7000);//注意:str.length() 不一定等于 str.getBytes().length

datagramSocket.send(datagramPacket);

//接收

byte[] bs = new byte[1000];

datagramPacket = new DatagramPacket(bs, 1000);

datagramSocket.receive(datagramPacket);

System.out.println(new String(bs, 0, datagramPacket.getLength()));

datagramSocket.close();

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值