Java 网络编程之 TCP/UDP

时间:2022-12-18 00:00:34

一、概述: 

  网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习。

         在 学习网络编程以前,很多初学者可能觉得网络编程是比较复杂的系统工程,需要了解很多和网络相关的基础知识,其实这些都不是很必需的。首先来问一个问题:你 会打手机吗?很多人可能说肯定会啊,不就是按按电话号码,拨打电话嘛,很简单的事情啊!其实初学者如果入门网络编程的话也可以做到这么简单!

         网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据。程序员所作的事情就是把数据发送到指定的位置,或者接收到指定的数据,这个就是狭义的网络编程范畴。在发送和接收数据时,大部分的程序设计语言都设计了专门的API实现这些功能,程序员只需要调用即可。所以,基础的网络编程可以和打电话一样简单。

         下面就开始Java语言的网络编程技术学习吧。

 在现有的网络中,网络通讯的方式主要有两种:

1、 TCP(传输控制协议)方式

2、 UDP(用户数据报协议)方式

二、 服务器端网络编程步骤

   

1、 监听端口

服务器端属于被动等待连接,所以服务器端启动以后,不需要发起连接,而只需要监听本地计算机的某个固定端口即可。

这个端口就是服务器端开放给客户端的端口,服务器端程序运行的本地计算机的IP地址就是服务器端程序的IP地址。

2、 获得连接

当客户端连接到服务器端时,服务器端就可以获得一个连接,这个连接包含客户端的信息,例如客户端IP地址等等,服务器端和客户端也通过该连接进行数据交换。

一般在服务器端编程中,当获得连接时,需要开启专门的线程处理该连接,每个连接都由独立的线程实现。

3、 交换数据

服务器端通过获得的连接进行数据交换。服务器端的数据交换步骤是首先接收客户端发送过来的数据,然后进行逻辑处理,再把处理以后的结果数据发送给客户端。简单来说,就是先接收再发送,这个和客户端的数据交换数序不同。

其实,服务器端获得的连接和客户端连接是一样的,只是数据交换的步骤不同。

当然,服务器端的数据交换也是可以多次进行的。

在数据交换完成以后,关闭和客户端的连接。

4、 关闭连接

当服务器程序关闭时,需要关闭服务器端,通过关闭服务器端使得服务器监听的端口以及占用的内存可以释放出来,实现了连接的关闭。

         其实服务器端编程的模型和呼叫中心的实现是类似的,例如移动的客服电话10086就是典型的呼叫中心,当一个用户拨打10086时,转接给一个专门的客服人员,由该客服实现和该用户的问题解决,当另外一个用户拨打10086时,则转接给另一个客服,实现问题解决,依次类推。

         在服务器端编程时,10086这个电话号码就类似于服务器端的端口号码,每个用户就相当于一个客户端程序,每个客服人员就相当于服务器端启动的专门和客户端连接的线程,每个线程都是独立进行交互的。

         这就是服务器端编程的模型,只是TCP方式是需要建立连接的,对于服务器端的压力比较大,而UDP是不需要建立连接的,对于服务器端的压力比较小罢了。

三、采用TCP套接字传输例子

package com.zyc.TCP_IP;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;


public class Client {
public static void main(String args[]){
PrintWriter writer = null ;
Socket socket = null ;
BufferedReader reader = null ;
try {
//建立Socket
socket = new Socket("localhost",8888) ;
//获取输出流,向服务器端发送消息
writer = new PrintWriter(socket.getOutputStream()) ;
//发送数据
writer.write("我是客户端,我向你发送了一条消息") ;
writer.flush() ;
//很重要,结束输出
socket.shutdownOutput() ;
//接受服务器端发的消息
reader = new BufferedReader(new InputStreamReader(socket.getInputStream())) ;
String str = null ;
while(null!=(str = reader.readLine())){
System.out.println("我是客户端 :服务器回应消息 :"+str);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
writer.close() ;
try {
reader.close() ;
writer.close() ;
socket.close() ;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

***********************************************************************************************

package com.zyc.TCP_IP;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;


public class Server_receive_Thread  extends Thread{
InputStream is = null ;
BufferedReader bf = null ;
PrintWriter writer = null ;
private Socket socket ;
public  Server_receive_Thread(Socket socket){
this.socket = socket ;
}
@Override
public void run() {
//获取客户端信息
try {
is = socket.getInputStream() ;
bf = new BufferedReader(new InputStreamReader(is)) ;
String str = null ;
while(null!=(str = bf.readLine())){
System.out.println("我是服务器端,客户端发来信息 :"+str);
}
//向客户端回应消息
writer = new PrintWriter(socket.getOutputStream()) ;
writer.write("我是服务器端,我回应你了") ;
writer.flush() ;
} catch (IOException e) {
e.printStackTrace();
}finally{
writer.close() ;
try {
bf.close() ;
is.close() ;
socket.close() ;
} catch (IOException e) {
e.printStackTrace();
}

}

}


}

************************************************************************************************

package com.zyc.TCP_IP;


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;


public class Server{
public static void main(String args[]){
ServerSocket serverSocket = null ;
Socket socket = null ;
int count = 0 ;
try{
//建立ServerSocket
serverSocket = new ServerSocket(8888) ;
//调用accept()方法
System.out.println("服务器启动,等待客户端连接.....");
while(true){
count++ ;
socket = serverSocket.accept() ;
Server_receive_Thread threadReceive = new Server_receive_Thread(socket) ;
threadReceive.start() ;
InetAddress address = socket.getInetAddress() ;
System.out.println("第"+count+"个客户端连接,IP:"+address);
}

}catch(Exception e){
e.printStackTrace() ;
}finally{
try{
socket.close() ;
serverSocket.close() ;
}catch(Exception e){
e.printStackTrace() ;
}
}
}
}

****************************************************************************************

采用UDP套接字传输 :

package com.zyc.UDP;


import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;


public class Client {
public static void main(String args[]){
DatagramSocket socket = null ;
try{
//定义服务器地址,端口号,数据
InetAddress address = InetAddress.getByName("localhost") ;
int port = 65000 ;
byte[]data = "我是客户端,这是我发送的消息".getBytes() ;
//创建数据报
DatagramPacket packet = new DatagramPacket(data, data.length,address,port) ;
//创建DatagramSocket 对象
socket = new DatagramSocket() ;

//向服务器端发送消息
socket.send(packet) ;

//接受服务器端发送的消息
//创建数据报
byte[]data2 = new byte[1024] ;
DatagramPacket packet2 = new DatagramPacket(data2,data2.length) ;
//接受服务器端响应的数据
socket.receive(packet2) ;
//读取数据
String reply = new String (data2,0,packet2.getLength()) ;
System.out.println("我是客户端,服务器说 :"+reply);
}catch(Exception e){
e.printStackTrace() ;
}finally{
// socket.close() ;
}
}
}

**************************************************************************************************

package com.zyc.UDP;


import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;


public class Server {
public static void main(String args[]){
DatagramSocket datagramSocket  = null ;
int count = 0 ;
try{

byte[]data = new byte[1024] ;
DatagramPacket packet = new DatagramPacket(data,data.length) ;
datagramSocket = new DatagramSocket(65000) ;
System.out.println("服务器端已启动,等待客户端接入 ...");

// while(true){
// //建立DataGramSocket,指定端口
// datagramSocket = new DatagramSocket(65000) ;
// Server_operation_Thread threadOperate = new Server_operation_Thread(datagramSocket) ;
// threadOperate.start() ;
// }
while(true){
count++ ;

//接受客户端发送的数据源
datagramSocket.receive(packet) ;
InetAddress address2 =packet.getAddress() ;
System.out.println("第"+count+"个客户端成功接入,IP:"+address2);
//读取数据
String info = new String(data,0,packet.getLength()) ;
System.out.println("我是服务器端:客户端发来消息 :"+info);
//向客户端响应数据
InetAddress address = packet.getAddress() ;
int port = packet.getPort() ;
byte[] data2 = "欢迎你 ".getBytes() ;
//创建数据报,包含响应数据信息
DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address,port) ;
//响应客户端

datagramSocket.send(packet2) ;
}
  }catch(Exception e){
e.printStackTrace() ;
}finally{
datagramSocket.close() ;
}
}
}


************************************************************************************