java网络通讯(UDP与TCP)

什么是计算机网络

通俗讲:两台电脑连在一起就组成了一个计算机网络。我们通过光钎连接到电信的网关,中国电信通过海底光缆和美国电信网关连接,你就是和全世界的在线用户连着。

网络编程就是在两个或连个以上的设备之间传输数据

什么是网络通信协议

网络通信协议就像我们的中文一样,她就是我们之间的共同语言,他规定了我们之间怎么说话,我先说什么你再说什么,你怎么说,而我怎么听。而网络通信得先规定一些俗称的网络通信协议,先说好,两台计算机之间什么收发信息,信息格式是什么,信息怎么发,怎么接受,而万一出错怎么办怎么处理。

UDP和TCP

TCP和TCP都是传输层协议

网络应用中基本上都是TCP和UDP,TCP是面向连接的通信协议,UDP是无连接的通信协议。

TCP协议特点

传输控制协议,提供的是面向连接,可靠的字节流服务。

当客户和服务器彼此交换数据前,必须现在双方之间建立一个TCP连接,之后才能传输数据。

TCP提供超时重发,丢弃数据,检验数据,流量控制等功能,保证数据能从一端到另一端。


UDP协议特点

UDP不提供可靠性,它只能把应用程序传给IP层的数据包发送出去,但是并不能保证他们能到达目的地。

UDP传输数据时是有大小限制的,每一个被传输的数据包必须限定在64kB之内。

由于UDP在传输数据报前不用再客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。

应用

TCP通信在网络上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。但是可靠的传输是要付出代价的,对数据内容正确性的检验必然占用计算机的处理时间和网络的宽带,因此TCP传输的效率不如UDP高。

UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中Client/sever 应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用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.

Java编写UDP网络程序

相关类介绍:

DatagramSocket

有如下构造方法

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

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

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

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

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

发送数据使用DatagramSocket.send(DatagramPacketp)方法;

接收数据使用DatagramSocket.receive( DatagramPacketp)方法;

DatagramPacket

Datagrampacket类有如下构造方法:

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

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

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


InetAddress

Java中对Ip地址进行包装的类,。DatagramPacket.getAddress()可以获取发送或接收方的IP地址,DatagramPacket.getPort()可以获取发送或接受方的端口


UDP程序例子

发送数据代码:


接收数据代码


Java编写TCP网络程序

ServerSocket

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

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

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

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

Socket

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

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

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

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

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

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

 

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


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

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

例子

服务器代码:

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
	public static void main(String[] args) throws Exception {
		//建立服务器
		ServerSocket ss=new ServerSocket(7000);
		while(true){
			//与客户端建立连接
			Socket s=ss.accept();
			//创建匿名类对象,并启动此对象的一个线程
			new Thread(new Servicer(s)).start();
		}
	}
};
//建立Servicer类
class Servicer implements Runnable{
	Socket s;//得到Socket类的引用s
	//创建构造方法
	public Servicer(Socket s) {
		this.s=s;
	}

	//重写run()方法启动线程
	@Override
	public void run() {
		
		try {
			//得到输入输出流
			InputStream ips=s.getInputStream();
			OutputStream ops=s.getOutputStream();
			//将字节流转换成字符流并使用BuffeedReader读取,碰到换行才结束
			BufferedReader br=new BufferedReader(new InputStreamReader(ips));
			//读不同的数据类型
			DataOutputStream dos=new DataOutputStream(ops);
			
			while(true){
				//按行读取客户端输入的内容
				String strWord=br.readLine();
				//判断内容是否为quit,如果是结束循环
				if(strWord.equalsIgnoreCase("quit")){
					break;
				}
				//将得到的字符串转换为StringBuffer并且反转,最后变为String存入strEcho中
				String strEcho=new StringBuffer(strWord).reverse().toString();
				//将内容写给客户端
				dos.writeBytes(strWord+"------>"+strEcho+System.getProperty("line.separator"));
			}
			br.close();
			dos.close();
			s.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
}

客户端代码


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;

public class TcpClient {
	public static void main(String args[]) throws Exception {
		Socket s=new Socket(InetAddress.getLocalHost(), 7000);
		
		//输入输出流接收或发送数据
		InputStream ips = s.getInputStream();
		OutputStream ops = s.getOutputStream();
		
		//字符流按行读取
		BufferedReader brKey = new BufferedReader(new InputStreamReader(
				System.in));
		//得到输出流
		DataOutputStream dos = new DataOutputStream(ops);
		//接收服务器端的数据
		BufferedReader brNet = new BufferedReader(new InputStreamReader(ips));
		
		while(true){
		//按行读取数据
		  String strWord = brKey.readLine();  
            dos.writeBytes(strWord + System.getProperty("line.separator"));//写数据加入换行符发送到服务器
            //如果输入输入为quit
            if("quit".equalsIgnoreCase(strWord)){  
                break;  
            }else{  
                System.out.println(brNet.readLine());  //将服务器数据打印输出
            }  
		}
		dos.close();
		brNet.close();
		brKey.close();
		s.close();
	}
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值