• TCP/UDP编程实例


    JAVA中TCP/UDP编程实例

    Apr 18th,2012 1482 / T:0
     

    开发时用127.0.0.1测试,关于127.0.0.1我就不多说了

    首先我们必须了解我们能用的端口地址只能在0~65535之间

    其中0~1023之间的端口是用于一些知名的网络服务和应用,用户的普通网络应用程序应该使用1024以上的端口.

    我一般用8000以上,网络应用中基本上都是TCP(Transmission Control Protocol传输控制协议)和UDP(User Datagram Protocol用户数据报协议),TCP是面向连接的通信协议,UDP是无连接的通信协议.

    JAVA中Socket连接套接字

    Java分别为TCP和UDP提供了相应的类

    1. TCP是java.net.ServerSocket(用于服务器端)和java.net.Socket(用于客户端);
    2. UDP是java.net.DatagramSocket.

    1.Java编写UDP网络程序

    1.1,DatagramSocket

    DatagramSocket有如下构造方法:

    1,DatagramSocket() :构造数据报套接字并将其绑定到本地主机上任何可用的端口。

    2,DatagramSocket(int port):创建数据报套接字并将其绑定到本地主机上的指定端口。

    3,DatagramSocket(int port, InetAddress laddr):创建数据报套接字,将其绑定到指定的本地地址。即指定网卡发送和接收数据.

    如果在创建DatagramSocket对象时,没有指定网卡的IP 地址,在发送数据时,底层驱动程序会自动选择一块网卡去发送,在接收数据时,会接收所有的网卡收到的与端口一致的数据.

    发送信息时,可以不指定端口号,接收信息时,要指定端口号,因为要接收指定的数据.

    发送数据使用DatagramSocket.send(DatagramPacket p)方法,接收数据使用DatagramSocket.receive(DatagramPacket p)方法.

    1.2,DatagramPacket

    DatagramPacket类有如下构造方法:

    1,DatagramPacket(byte[] buf, int length):构造 DatagramPacket,用来接收长度为length的数据包。

    2,DatagramPacket(byte[] buf, int length, InetAddress address, int port):构造数据报包,用来将长度为length的包发送到指定主机上的指定端口号。

    接收数据时使用第一次构造方法,发送数据时使用第二种构造方法.

    1.3,InetAddress

    Java中对IP地址进行包装的类,

    DatagramPacket.getAddress()可以获取发送或接收方的IP地址.DatagramPacket.getPort()可以获取发送或接收方的端口.

    1.4,UDP程序例子

    发送程序:

    import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;publicclassUdpSend{publicstaticvoid main(String[] args)throwsException{DatagramSocket ds =newDatagramSocket();String str ="hello , waynerQiu.com!";DatagramPacket dp =newDatagramPacket(str.getBytes(), str.length(),InetAddress.getByName("192.168.0.105"),3000);
    ds.send(dp);
    ds.close();//关闭连接}}

    接收程序:

    import java.net.DatagramPacket;import java.net.DatagramSocket;publicclassUdpRecv{publicstaticvoid main(String[] args)throwsException{DatagramSocket ds =newDatagramSocket(3000);byte[] buf =newbyte[1024];DatagramPacket dp =newDatagramPacket(buf, buf.length);
    ds.receive(dp);String str =newString(dp.getData(),0, dp.getLength());System.out.println(str);System.out.println("IP:"+ dp.getAddress().getHostAddress()+",PORT:"+ dp.getPort());
    ds.close();}}


     测试要先运行接收程序,再运行发送程序.如果接收程序没有接收到数据,则会一直阻塞,接收到数据后才会关闭程序.如果网络上没有数据发送过来,接收程序也没有阻塞,通常都是使用了一个已经被占用的端口.

    2,Java编写TCP网络程序

    2.1,ServerSocket

    编写TCP网络服务程序,首先要用到java.net.ServerSocket类用以创建服务器Socket.它的常用构造方法有:

    1,ServerSocket(int port):创建绑定到特定端口的服务器套接字。

    2,ServerSocket(int port, int backlog):利用指定的backlog(服务器忙时保持连接请求的等待客户数量),创建服务器套接字并将其绑定到指定的本地端口号。

    3,ServerSocket(int port, int backlog, InetAddress bindAddr):使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。

    2.2,Socket

    客户端要与服务器建立连接,必须先创建一个Socket对象,它的常用构造方法有:

    1,Socket(String host, int port):创建一个流套接字并将其连接到指定主机上的指定端口号。

    2,Socket(InetAddress address, int port):创建一个流套接字并将其连接到指定 IP 地址的指定端口号。

    3,Socket(InetAddress address, int port, InetAddress localAddr, int localPort):创建一个套接字并将其连接到指定远程端口上的指定远程地址。

    4,Socket(String host, int port, InetAddress localAddr, int localPort):创建一个套接字并将其连接到指定远程主机上的指定远程端口。

    对于通常情况的应用,使用第1个构造方法来创建客户端的Socket对象,并与服务器建立连接,是非常简单和方便的.

    服务器端程序调用ServerSocket.accept方法等待客户端的连接请求,一旦accept接收了客户端连接请求,该方法返回一个与该客户端建立了专线连接的Socket对象,不用程序去创建这个Socket对象.建立了连接的两个Socket是以IO流的方式进行数据交换的,Java提供了Socket.getInputStream返回Socket的输入流对象,Socket.getOutputStream返回Socket的输出流对象.

    2.3,TCP程序例子的服务器程序:

    import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;publicclassTcpServer{publicstaticvoid main(String[] args)throwsException{ServerSocket ss =newServerSocket(8000);Socket s = ss.accept();InputStream ips = s.getInputStream();OutputStream ops = s.getOutputStream();
    ops.write("hello,World!".getBytes());byte[] buf =newbyte[1024];int len = ips.read(buf);System.out.println(newString(buf,0, len));
    ips.close();
    ops.close();
    s.close();
    ss.close()}}

    在这个程序里,创建了一个在8000端口上等待连接的ServerSocket对象,当接收到一个客户的连接请求后,程序从与这个客户建立了连接的Socket对象中获得输入输出流对象,通过输出流首先向客户端发送一串字符,然后通过输入流读取客户端发送过来的信息,并将这些信息打印,然后关闭所有资源.

    要先运行服务器程序,然后才能运行客户端程序,当TCP服务器程序运行到Socket.accpet()方法等待客户连接时,accept方法将阻塞,一直到有客户连接请求到来,该方法才会返回,如果又没有请求到来,又没有发生阻塞,通常都是使用了一个已经被占用的端口.

    我们可以使用windows提供的telnet工具在命令行窗口中测试一下服务器程序:命令如下:telnet localhost 8000

    可以看到,telnet只要有输入就发送,因此我们如果想要在服务器端一次读多个字符的话,还需要进一步处理,看如下代码:

    import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;publicclassTcpServer{publicstaticvoid main(String[] args)throwsException{ServerSocket ss =newServerSocket(8000);Socket s = ss.accept();InputStream ips = s.getInputStream();BufferedReader br =newBufferedReader(newInputStreamReader(ips));OutputStream ops = s.getOutputStream();
    ops.write("hello,World!".getBytes());System.out.println(br.readLine());
    br.close();
    ops.close();
    s.close();
    ss.close()}}

    再次使用telnet工具可以看到,这次可以发送不止一个字符了,按回车键后发送数据到服务器端.

    2,Java编写TCP网络程序

    2.1,ServerSocket

    编写TCP网络服务程序,首先要用到java.net.ServerSocket类用以创建服务器Socket.它的常用构造方法有:

    1,ServerSocket(int port):创建绑定到特定端口的服务器套接字。

    2,ServerSocket(int port, int backlog):利用指定的backlog(服务器忙时保持连接请求的等待客户数量),创建服务器套接字并将其绑定到指定的本地端口号。

    3,ServerSocket(int port, int backlog, InetAddress bindAddr):使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。

    2.2,Socket

    客户端要与服务器建立连接,必须先创建一个Socket对象,它的常用构造方法有:

    1,Socket(String host, int port):创建一个流套接字并将其连接到指定主机上的指定端口号。

    2,Socket(InetAddress address, int port):创建一个流套接字并将其连接到指定 IP 地址的指定端口号。

    3,Socket(InetAddress address, int port, InetAddress localAddr, int localPort):创建一个套接字并将其连接到指定远程端口上的指定远程地址。

    4,Socket(String host, int port, InetAddress localAddr, int localPort):创建一个套接字并将其连接到指定远程主机上的指定远程端口。

    对于通常情况的应用,使用第1个构造方法来创建客户端的Socket对象,并与服务器建立连接,是非常简单和方便的.

    服务器端程序调用ServerSocket.accept方法等待客户端的连接请求,一旦accept接收了客户端连接请求,该方法返回一个与该客户端建立了专线连接的Socket对象,不用程序去创建这个Socket对象.建立了连接的两个Socket是以IO流的方式进行数据交换的,Java提供了Socket.getInputStream返回Socket的输入流对象,Socket.getOutputStream返回Socket的输出流对象.

    2.3,TCP程序例子的服务器程序:

    import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;publicclassTcpServer{publicstaticvoid main(String[] args)throwsException{ServerSocket ss =newServerSocket(8000);Socket s = ss.accept();InputStream ips = s.getInputStream();OutputStream ops = s.getOutputStream();
    ops.write("hello,World!".getBytes());byte[] buf =newbyte[1024];int len = ips.read(buf);System.out.println(newString(buf,0, len));
    ips.close();
    ops.close();
    s.close();
    ss.close()}}

    在这个程序里,创建了一个在8000端口上等待连接的ServerSocket对象,当接收到一个客户的连接请求后,程序从与这个客户建立了连接的Socket对象中获得输入输出流对象,通过输出流首先向客户端发送一串字符,然后通过输入流读取客户端发送过来的信息,并将这些信息打印,然后关闭所有资源.

    要先运行服务器程序,然后才能运行客户端程序,当TCP服务器程序运行到Socket.accpet()方法等待客户连接时,accept方法将阻塞,一直到有客户连接请求到来,该方法才会返回,如果又没有请求到来,又没有发生阻塞,通常都是使用了一个已经被占用的端口.

    我们可以使用windows提供的telnet工具在命令行窗口中测试一下服务器程序:命令如下:telnet localhost 8000

    可以看到,telnet只要有输入就发送,因此我们如果想要在服务器端一次读多个字符的话,还需要进一步处理,看如下代码:

    import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;publicclassTcpServer{publicstaticvoid main(String[] args)throwsException{ServerSocket ss =newServerSocket(8000);Socket s = ss.accept();InputStream ips = s.getInputStream();BufferedReader br =newBufferedReader(newInputStreamReader(ips));OutputStream ops = s.getOutputStream();
    ops.write("hello,World!".getBytes());System.out.println(br.readLine());
    br.close();
    ops.close();
    s.close();
    ss.close()}}

    再次使用telnet工具可以看到,这次可以发送不止一个字符了,按回车键后发送数据到服务器端.

    2.5,TCP程序例子客户端程序:

    import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;publicclassTcpClient{publicstaticvoid main(String[] args)throwsException{if(args.length <2){System.out.println("Usage:java TcpClient ServerIP ServerPort");return}Socket s =newSocket(InetAddress.getByName(args[0]),Integer.parseInt(args[1]));InputStream ips = s.getInputStream();OutputStream ops = s.getOutputStream();BufferedReader brKey =newBufferedReader(newInputStreamReader(System. in ));DataOutputStream dos =newDataOutputStream(ops);BufferedReader brNet =newBufferedReader(newInputStreamReader(ips));while(true){String strWord = brKey.readLine();
    dos.writeBytes(strWord +System.getProperty("line.separator"));if("quit".equalsIgnoreCase(strWord)){break}else{System.out.println(brNet.readLine())}}
    dos.close();
    brNet.close();
    brKey.close();
    s.close()}}

    先运行服务器程序,再在命令行使用java TcpClient 192.168.0.3 8000,这样就启动了客户端程序.我们可以启动多个客户端程序.

    我们可以利用netstat工具来查看已经被使用的端口

  • 相关阅读:
    代码审计变成CTF
    updatexml()报错注入
    一道综合渗透题引发的updatexml()注入思考
    Visual Studio 调试技巧---指针,元素个数
    在Visual Studio中调试时,如何检查有关进程令牌的详细信息?
    在调试时,有什么更好的方法可以监视最后一个win32错误?
    从WinDbg中的转储查看操作系统版本和SP详细信息
    可以使用WinDbg将PE映像作为转储文件打开
    常见WinDbg问题及解决方案
    在崩溃转储中查找所有可能的上下文记录
  • 原文地址:https://www.cnblogs.com/lovelifeloveme/p/3141925.html
Copyright © 2020-2023  润新知