引言:
TCP/IP是一种网络通信协议,它规范了网络上所有通信设备的数据传送格式以及传送方式,是Internet上的基础协议。在TCP/IP协议组中有两种主要协议:
一)传输层协议
a)传输层控制协议(TCP)
它建立在面向连接的基础上。双方通信之前先建立连接,然后双方即可在其上发送数据流实现通信,使用完毕后再关闭连接。这种协议的优点是效率高,缺点是在建立连接关闭连接时需要额外的开销。
b)用户数据报协议(UDP)
UDP较TCP简单不少,是对IP协议组的扩充。与TCP不同,UDP是提供面向无连接、“不可靠”的数据报服务。
二)应用层协议
应用层中定义了许多高层协议。TELNET(远程终端访问)、FTP(文件传输协议)、SMTP(简单邮件传输协议)、DNS(域名服务)、HTTP(超文本传输协议)等。
Socket编程
它允许程序员把网络连接当成一个流,并向这个流读写字节。Socket对程序员隐藏了网络的低层细节,如纠错、包大小、包和重传、网络地址等。
A)基于TCP的Socket编程
需要编写服务器端和客户端两个应用程序。主要用到两个类,Socket、ServerSocket。它们都位于java.net包中。
1)服务器端编写步骤
a)创建一个等待连接的ServerSocket对象。
b)调用ServerSocket的accept方法侦听客户端的连接请求。当侦听到一个连接后,返回一个Socket对象,连接成功。
c)创建与Socket对象绑定的输入、输出流,并建立相应的数据输入输出流。
d)通过数据输入输出流与客户端进行数据读写,完成双向通信。
e)当客户端断开连接后,关闭各个流,结束通信。
f)不断执行(b~e)
请看示例代码:
import java.io.*; import java.net.*; import static java.lang.System.*; public class TestServer { public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(6666); out.println("start......");
while(true){ Socket s = ss.accept(); // 阻塞式 err.println("a client accepted");
//建立输入流,接收客户端发来的数据 InputStream is = s.getInputStream(); DataInputStream dis = new DataInputStream(is); out.println(dis.readUTF());// 阻塞式
//建立输出流,向客户端发送数据 OutputStream os = s.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); dos.writeUTF("Server:hello client!..."); in.close(); out.close(); ss.close();
} } }
2)客户端编写步骤
a)创建指定服务器上指定端口号的Socket对象
b)创建与Socket对象绑定的输入、输出流,并建立相应的数据输入输出流。
c)通过数据输入输出流与客户端进行数据读写,完成双向通信。
d)关闭与服务器的连接,关闭各个流,结束通信。
示例代码:
import java.io.*; import java.net.*; import static java.lang.System.*; public class TestClient { public static void main(String[] args) throws UnknownHostException, IOException { Socket s = new Socket("127.0.0.1", 6666); OutputStream os = s.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); dos.writeUTF("client: hello server!..."); DataInputStream dis = new DataInputStream(s.getInputStream()); err.println(dis.readUTF()); } }
B)基于UDP的Socket编程
开发基于UDP协议的网络应用程序时,也要分别编写服务器端与客户端(逻辑上的,其实两端是对等的)。与TCP不同的是这两端程序基本架构是相同的。因此对于基于UDP的Socket编程就不分服务器端与客户端。具体如下:
a)建立一个DatagramSocket对象
b)进入收发数据报包的循环,直到数据传送完毕。
1)利用DatagramSocket处理接收到的数据
2)利用DatagramSocket发送数据
c)释放Socket连接
请看示例代码:
server端:
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; import java.util.Date; public class Server_udp { public static void main(String[] args) { try { DatagramSocket ds = new DatagramSocket(3000); System.out.println("waitting for connecting"); while (true) { byte[] buf = new byte[256]; //接收 DatagramPacket p = new DatagramPacket(buf, buf.length); ds.receive(p); System.out.println("client:" + new String(p.getData())); // sending for next //发送 buf = new Date().toString().getBytes(); p = new DatagramPacket(buf, buf.length, p.getAddress(), p.getPort()); ds.send(p); // System.out.println("already send..."); } } catch (SocketException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Client端:
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class Client_udp { public static void main(String[] args) throws IOException { DatagramSocket ds = new DatagramSocket(); // 发送 byte[] buf = new byte[256]; buf = "hello".getBytes(); DatagramPacket p = new DatagramPacket(buf, buf.length, InetAddress.getByName("localhost"), 3000); ds.send(p); // 接收 p = new DatagramPacket(buf, buf.length); ds.receive(p); System.out.println("server:" + new String(p.getData())); ds.close(); } }