引言:
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();
}
}