本文转自:http://www.cnblogs.com/cdtarena/archive/2013/04/10/3012282.html

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

127.0.0.1是回路地址,用于测试,相当于localhost本机地址,没有网卡,不设DNS都可以访问.

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

Socket连接套接字,Java分别为TCP和UDP提供了相应的类,TCP是java.net.ServerSocket(用于服务器端)和java.net.Socket(用于客户端);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程序例子

发送程序:

  1. import java.net.DatagramPacket;
  2. import java.net.DatagramSocket;
  3. import java.net.InetAddress;
  4. publicclass UdpSend {
  5. publicstaticvoid main(String[] args) throws Exception {
  6. DatagramSocket ds = new DatagramSocket();
  7. String str = "hello , world!";
  8. DatagramPacket dp = new DatagramPacket(str.getBytes(),str.length(),InetAddress.getByName("192.168.0.105"),3000);
  9. ds.send(dp);
  10. ds.close(); //关闭连接
  11. }
  12. }

接收程序:

  1. import java.net.DatagramPacket;
  2. import java.net.DatagramSocket;
  3. publicclass UdpRecv {
  4. publicstaticvoid main(String[] args) throws Exception {
  5. DatagramSocket ds = new DatagramSocket(3000);
  6. byte[] buf = newbyte[1024];
  7. DatagramPacket dp = new DatagramPacket(buf,buf.length);
  8. ds.receive(dp);
  9. String str = new String(dp.getData(),0,dp.getLength());
  10. System.out.println(str);
  11. System.out.println("IP:" + dp.getAddress().getHostAddress() + ",PORT:" + dp.getPort());
  12. ds.close();
  13. }
  14. }

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

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程序例子的服务器程序:

  1. import java.io.InputStream;
  2. import java.io.OutputStream;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5. publicclass TcpServer {
  6. publicstaticvoid main(String[] args) throws Exception {
  7. ServerSocket ss = new ServerSocket(8000);
  8. Socket s = ss.accept();
  9. InputStream ips = s.getInputStream();
  10. OutputStream ops = s.getOutputStream();
  11. ops.write("hello,World!".getBytes());
  12. byte[] buf = newbyte[1024];
  13. int len = ips.read(buf);
  14. System.out.println(new String(buf,0,len));
  15. ips.close();
  16. ops.close();
  17. s.close();
  18. ss.close();
  19. }
  20. }

在这个程序里,创建了一个在8000端口上等待连接的ServerSocket对象,当接收到一个客户的连接请求后,程序从与这个客户建立了连接的Socket对象中获得输入输出流对象,通过输出流首先向客户端发送一串字符,然后通过输入流读取客户端发送过来的信息,并将这些信息打印,然后关闭所有资源.要先运行服务器程序,然后才能运行客户端程序,当TCP服务器程序运行到Socket.accpet()方法等待客户连接时,accept方法将阻塞,一直到有客户连接请求到来,该方法才会返回,如果又没有请求到来,又没有发生阻塞,通常都是使用了一个已经被占用的端口. 我们可以使用windows提供的telnet工具在命令行窗口中测试一下服务器程序:命令如下:telnet localhost 8000 可以看到,telnet只要有输入就发送,因此我们如果想要在服务器端一次读多个字符的话,还需要进一步处理,看如下代码:

  1. import java.io.BufferedReader;
  2. import java.io.InputStream;
  3. import java.io.InputStreamReader;
  4. import java.io.OutputStream;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7. publicclass TcpServer {
  8. publicstaticvoid main(String[] args) throws Exception {
  9. ServerSocket ss = new ServerSocket(8000);
  10. Socket s = ss.accept();
  11. InputStream ips = s.getInputStream();
  12. BufferedReader br = new BufferedReader(new InputStreamReader(ips)); //对InputStream进行包装,增加了缓存
  13. OutputStream ops = s.getOutputStream();
  14. ops.write("hello,World!".getBytes());
  15. System.out.println(br.readLine());
  16. br.close(); //www.cdtarena.com关闭包装类,会自动关闭里面的基类
  17. ops.close();
  18. s.close();
  19. ss.close();
  20. }
  21. }

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

2.4,TCP程序例子改进后的服务器程序:

大多数情况下,服务器端都要服务多个客户端,但一次accept方法调用只接收一个连接,因此,要把accept方法放在一个循环语句中,这样就可以接收多个连接.每个连接的数据交换代码也放在一个循环中,这样才能保证两者可以不停地交换数据.

每个连接的数据交换代码必须放在独立的线程中运行,否则,这在段代码运行期间,就没法执行其他的程序代码,accept方法也得不到调用,新的连接无法进入.

下面是一个例子,客户端向服务器发送一个字符串,服务器将这个字符串中的所有字符反向排列后回送给客户端.客户端输入"quit",退出程序.

  1. import java.io.BufferedReader;
  2. import java.io.DataOutputStream;
  3. import java.io.InputStream;
  4. import java.io.InputStreamReader;
  5. import java.io.OutputStream;
  6. import java.net.ServerSocket;
  7. import java.net.Socket;
  8. publicclass TcpServer {
  9. publicstaticvoid main(String[] args) throws Exception {
  10. ServerSocket ss = new ServerSocket(8000);
  11. while(true){
  12. Socket s = ss.accept();
  13. new Thread(new Servicer(s)).start();
  14. }
  15. }
  16. }
  17. class Servicer implements Runnable{
  18. Socket s;
  19. public Servicer(Socket s){
  20. this.s = s;
  21. }
  22. publicvoid run(){
  23. try{
  24. InputStream ips = s.getInputStream();
  25. OutputStream ops = s.getOutputStream();
  26. BufferedReader br = new BufferedReader(new InputStreamReader(ips));
  27. DataOutputStream dos = new DataOutputStream(ops);
  28. while(true){
  29. String strWord = br.readLine();
  30. if(strWord.equalsIgnoreCase("quit")){
  31. break;
  32. }
  33. String strEcho = (new StringBuffer(strWord).reverse().toString());
  34. dos.writeBytes(strWord + "------->" + strEcho + System.getProperty("line.separator"));
  35. }
  36. br.close();
  37. dos.close();
  38. s.close();
  39. }catch(Exception e){
  40. e.printStackTrace();
  41. }
  42. }
  43. }

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

  1. import java.io.BufferedReader;
  2. import java.io.DataOutputStream;
  3. import java.io.InputStream;
  4. import java.io.InputStreamReader;
  5. import java.io.OutputStream;
  6. import java.net.InetAddress;
  7. import java.net.Socket;
  8. publicclass TcpClient {
  9. publicstaticvoid main(String[] args) throws Exception{
  10. if(args.length < 2){
  11. System.out.println("Usage:java TcpClient ServerIP ServerPort");
  12. return ;
  13. }
  14. Socket s = new Socket(InetAddress.getByName(args[0]),Integer.parseInt(args[1]));
  15. InputStream ips = s.getInputStream();
  16. OutputStream ops = s.getOutputStream();
  17. BufferedReader brKey = new BufferedReader(new InputStreamReader(System.in));
  18. DataOutputStream dos = new DataOutputStream(ops);
  19. BufferedReader brNet = new BufferedReader(new InputStreamReader(ips));
  20. while(true){
  21. String strWord = brKey.readLine();
  22. dos.writeBytes(strWord + System.getProperty("line.separator"));
  23. if("quit".equalsIgnoreCase(strWord)){
  24. break;
  25. }else{
  26. System.out.println(brNet.readLine());
  27. }
  28. }
  29. dos.close();
  30. brNet.close();
  31. brKey.close();
  32. s.close();
  33. }
  34. }

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

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

Java TCP/UDP网络通信编程的更多相关文章

  1. Java中的TCP/UDP网络通信编程

    127.0.0.1是回路地址,用于测试,相当于localhost本机地址,没有网卡,不设DNS都可以访问. 端口地址在0~65535之间,其中0~1023之间的端口是用于一些知名的网络服务和应用,用户 ...

  2. 三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

    这篇文章主要是来做(da)推(guang)介(gao)的!由于这两年接触到了比较多的这方面的知识,不想忘了,我决定把他们记录下来,所以决定在GitBook用半年时间上面写下来,这是目前写的一节,后面会 ...

  3. 一个项目看java TCP/IP Socket编程

    前一段时间刚做了个java程序和网络上多台机器的c程序通讯的项目,遵循的是TCP/IP协议,用到了java的Socket编程.网络通讯是java的强项,用TCP/IP协议可以方便的和网络上的其他程序互 ...

  4. TCP UDP基本编程(一)

    tcp udp均可以用来网络通信,在使用之前建议先搜索一下相关网络连接的基本知识,可以更好的理解和使用,tcp建议看下如下文章:https://blog.csdn.net/chuangsun/arti ...

  5. java tcp ip网络编程(二) 套接字的基本使用

    ##基本套接字的使用 linux系统把网络io抽象成socket,对网络的编程就是对socket的编程. java把套接字抽象成类似的类 InetAddress SocketAddress 识别jav ...

  6. Go语言TCP/UDP Socket编程

    1. TCP编程 TCPClient // TCPClient project main.go package main import ( "fmt" "net" ...

  7. tcp/udp socket编程异同

    一.TCP与UDP的区别 基于连接与无连接 对系统资源的要求(TCP较多,UDP少) UDP程序结构较简单 流模式与数据报模式 TCP保证数据正确性,UDP可能丢包 TCP保证数据顺序,UDP不保证 ...

  8. [Java] Tcp/udp 简单通信

    本文转自  我自己的博客guozeyiblog.cn 欢迎来訪 效果图: //UDP通信 import java.awt.*; import java.awt.event.ActionEvent; i ...

  9. TCP/UDP网络编程的基础知识与基本示例(windows和Linux)

    一.TCP编程的一般步骤 服务器端: 1.创建一个socket,用函数socket() 2.绑定IP地址.端口等信息到socket上,用函数bind() 3.开启监听,用函数listen() 4.接收 ...

随机推荐

  1. ps、top 、free查看用户资源信息

      查看root用户的进程信息. 运行命令: ps -u root 查看oracle用户的进程信息. 运行命令: ps -u oracle 若查看现在的资源占用情况,如何呢? 运行命令: top 可以 ...

  2. 堆栈帧的组织——C/C++内存管理必须掌握

    程序栈 说到堆栈帧,你得先说说程序栈. 记忆功能程序堆栈区是支持操作,通常共享堆. 程序栈通常占领内存区域的下部,而堆用的是上部. 程序栈存放栈帧,栈帧有时候也称为活跃记录或活跃帧.栈帧存放函数參数和 ...

  3. Go by Example

    Go by Example Go is an open source programming language designed for building simple, fast, and reli ...

  4. tar解压出错

    现象 # tar -zxvf aaa.tar.gz tar: This does not look like a tar archive tar: Skipping to next header ta ...

  5. ORACLE函数之日期时间运算函数

    1            ADD_MONTHS 格式:ADD_MONTHS(D,N) 说明:返回日期时间D加N月后相应的日期时间.N为正时则表示D之后:N为负时则表示为D之前.N为小数则会自己主动先删 ...

  6. 对ORA-01795: 列表中的最大表达式数为 1000的处理(算法:计算数量及切割)

    /** * @category  * 原:strIDs in ( 100001,100002,100003,....................,110001,120001,130001,1400 ...

  7. Uva11464 开关问题

    给一个n×n的01矩阵,你的任务是将尽量少的0变成1,是的每个元素的上下左右的位置(如果存在的话)的之和均为偶数.1<=n<=15. 如果暴力整个矩阵,那么时间复杂度是O(2^(n*n)) ...

  8. J2SE基础:1.类和对象基础

    什么是对象 在Java语言,全部的人,事物或者模块都是一个对象. 同样的对象具有一些同样的特性. 狗,猫,蛇3个对象(动物的对象) 苹果,梨,桔子3个对象(水果的对象) 什么是类 能够将现实生活中的对 ...

  9. MongoDB获得短暂的

    大约MongoDB该数据是现在比较少.和大多数英文网站.最上面的经笔者从官方网站翻译.请翻译或误解之处请作证.然后,我们将继续关注MongoDB,和翻译“Developer Zone”和“Admin ...

  10. 工程PMO工作

     算起来,这是第一次以项目PMO人员的身份參与项目.尽管非常可惜没有从头參与,也没有參与到项目结束.仅仅有短短的两个月,但对项目PMO也可略窥一斑.如今就当个流水账写一写吧. 进项目组的时候,是中 ...