1)TCP程序设计
在Java中使用Socket(即套接字)完成TCP程序的开发,使用此类可以方便的的建立可靠的、双向的、持续的、点对点的通信连接
在Socket的程序开发中,服务器端使用ServerSocket等待客户端的连接,对于Java的网络程序来说,每一个客户端都是用一个Socket对象表示。
第一个TCP程序
package tcp.socket;
import java.io.PrintStream;
import .ServerSocket;
import .Socket;
public class HelloServer {
public static void main(String[] args) throws Exception {
ServerSocket server = null;//声明一个客户端ServerSocket对象
Socket client = null;//一个Socket对应一个客户端
PrintStream out = null;//声明打印流,一项客户端输出
server = new ServerSocket(8888);//在端口号:8888上等待客户端连接
System.out.println("服务器运行,等待客户端连接::::");
client = server.accept();//程序在次阻塞,等待客户端连接
String str = "hello world;";
out = new PrintStream(client.getOutputStream());//实例化打印输出流对象,输出信息
System.out.println("客户端已连接成功。");
out.print(str);
out.close();
client.close();
server.close();
}
}
结果:
服务器运行,等待客户端连接::::
客户端已连接成功。
package tcp.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import .Socket;
import .UnknownHostException;
public class HelloClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket client = null;
client = new Socket("localhost", 8888);
BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
String str = buf.readLine();
System.out.println("服务器输出的内容是:"+str);
client.close();
buf.close();
}
}
结果:
服务器输出的内容是:hello world;
案例:---Echo程序
Echo程序是一个网络编程通信交互的经典案例,称为回应程序,即客户端输入哪些内容,服务端在这些内容前面加上“ECHO: ” 并将信息发给客户端,下面就是这样一个程序,
package tcp.echo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import .ServerSocket;
import .Socket;
public class EchoServer {
public static void main(String[] args) throws IOException {
ServerSocket server = null;//声明一个客户端ServerSocket对象
Socket client = null;//一个Socket对应一个客户端
PrintStream out = null;//声明打印流,一项客户端输出
BufferedReader buf = null;//用于接受客户端发送来的信息
server = new ServerSocket(8888);//在端口号:8888上等待客户端连接
boolean f = true;
while (f) {
System.out.println("服务器运行,等待客户端连接::::");
client = server.accept();
buf = new BufferedReader(new InputStreamReader(client.getInputStream()));//得到客户端的输入信息
out = new PrintStream(client.getOutputStream());//输出信息给Socket
boolean flag = true;
int count = 0 ;
while(flag){
String str = buf.readLine();
if (str==null||"".equals(str)) {
flag = false;
}else {
if (str.equals("bye")) {
flag = false;
}else {
out.println("ECHO: "+str);
}
}
System.out.println("完成返回--->"+count++);
}
out.close();
client.close();
}
server.close();
}
}
结果:
服务器运行,等待客户端连接::::
完成返回--->0
完成返回--->1
完成返回--->2
服务器运行,等待客户端连接::::
package tcp.echo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import .Socket;
import .UnknownHostException;
public class EchoClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket client = null;
client = new Socket("localhost",8888);
BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));//接受服务器端输入的信息
PrintStream out = new PrintStream(client.getOutputStream());
boolean flag = true;
while (flag) {
System.out.println("输入信息:");
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String str = input.readLine();
out.println(str);
if ("bye".equals(str)) {
flag = false;
}else {
String echo = buf.readLine();
System.out.println(echo);
}
}
out.close();
buf.close();
client.close();
}
}
结果:
输入信息:
你好
ECHO: 你好
输入信息:
hello world
ECHO: hello world
输入信息:
bye
在服务器上运用多线程
对于服务器来说,如果 要加入多线程机制,则应该在每个用户连接后启动一个新的线程。所以先建立一个EchoThread的类,此类专门用于处理多线程操作,此时的多线程使用Runnable接口实现。
package tcp.echoThread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import .Socket;
public class EchoThread implements Runnable{
private Socket client = null;
public EchoThread(Socket client) {
this.client = client;
}
@Override
public void run() {
PrintStream out = null;
BufferedReader buf = null;
try {
buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintStream(client.getOutputStream());
boolean flag = true;
int count = 0;
while (flag) {
String str = buf.readLine();
if (str==null||"".equals(str)) {
flag = false;
}else {
if (str.equals("bye")) {
flag = false;
}else {
out.println("ECHO: "+str);
}
}
System.out.println("完成返回--->"+count++ +"线程名:"+Thread.currentThread().getName());
}
out.close();
client.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package tcp.echoThread;
import java.io.IOException;
import .ServerSocket;
import .Socket;
public class EchoThreadServer {
public static void main(String[] args) throws IOException {
ServerSocket server = null;
Socket client = null;
server = new ServerSocket(8888);
boolean f = true;
while (f) {
System.out.println("服务器运行,等待客户端连接::::");
client = server.accept();
new Thread(new EchoThread(client)).start();
}
}
}
结果:
服务器运行,等待客户端连接::::
服务器运行,等待客户端连接::::
完成返回--->0线程名:Thread-0
完成返回--->1线程名:Thread-0
服务器运行,等待客户端连接::::
完成返回--->0线程名:Thread-1
完成返回--->1线程名:Thread-1
package tcp.echoThread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import .Socket;
import .UnknownHostException;
public class EchoThreadClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket client = null;
client = new Socket("localhost",8888);
BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));//接受服务器端输入的信息
PrintStream out = new PrintStream(client.getOutputStream());
boolean flag = true;
while (flag) {
System.out.println("输入信息:");
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String str = input.readLine();
out.println(str);
if ("bye".equals(str)) {
flag = false;
}else {
String echo = buf.readLine();
System.out.println(echo);
}
}
out.close();
buf.close();
client.close();
}
}
结果1:
输入信息:
第一个客户端测试:你好
ECHO: 第一个客户端测试:你好
输入信息:
你好
ECHO: 你好
输入信息:
结果2:
输入信息:
第二个客户端测试:你好
ECHO: 第二个客户端测试:你好
输入信息:
你好
ECHO: 你好
输入信息:
2)UDP程序设计
在Java中网络编程可以使用TCP和UDP两种协议模式,TCP的所有操作必须建立可靠的连接,这样肯定会浪费大量的系统性能,为了减少这种开销,在网络中又提供了另外一个传输协议----UDP(不可靠的连接)协议,这种协议在各个聊天工具中被广泛地应用。
使用UDP发送出去的信息,对方不一定会接受到,所有的信息使用该数据报的形式发送出去,所以着就要求客户端要始终等待服务器发送的信息才能进行接受,在Java中使用DatagramSocket和DatagramPacket类完成UDP程序开发。
使用UDP开发的网络程序类似与平常使用的手机,如果想让手机接受信息,必须得先开机才行,手机就相当于客户端。
package tcp.udp;
import java.io.IOException;
import .DatagramPacket;
import .DatagramSocket;
public class UDPClient {
public static void main(String[] args) throws IOException {
DatagramSocket ds = null;
byte[] buf = new byte[1024]; //定义接受数据报的字节数组
DatagramPacket dp = null;
ds = new DatagramSocket(9999); //此客户端在9999端口监听
dp = new DatagramPacket(buf, 1024); //指定接受数据的长度为1024
System.out.println("等待接受数据。");
ds.receive(dp); //接受数据
String str = new String(dp.getData(),0,dp.getLength())+"from"+dp.getAddress().getHostAddress()+":"+dp.getPort();
System.out.println(str);
ds.close();
}
}
结果:
等待接受数据。
hello world!from127.0.0.1:3333
package tcp.udp;
import java.io.IOException;
import .DatagramPacket;
import .DatagramSocket;
import .InetAddress;
public class UDPServer {
public static void main(String[] args) throws IOException {
DatagramSocket ds = null; //声明DatagramSocket对象
DatagramPacket dp = null; //声明DatagramPacket对象
ds = new DatagramSocket(3333);//服务器端在3333端口监听
String str = "hello world!"; //准备好要发送的信息
//此处向客户端所在的9999端口发送信息
dp = new DatagramPacket(str.getBytes(), str.length(),InetAddress.getByName("localhost"),9999);
System.out.println("发送信息。");
ds.send(dp); //发送信息报
ds.close();
}
}
结果:
发送信息。
总结:
- InteAddress是表示IP地址的操作类,可以通过子类指定要连接的主机名称
- 在开发中如果想要取得一个网络资源可以使用URL类进行定位,然后使用IO流的方式进行读取
- 是用URLEncode可以为信息编码,使用URLDecoder可以为编码的内容进行解码操作
- ServerSocket主要用与TCP协议的服务器程序开发,使用accept()方法等待客户端连接,每一个连接的客户端都是用一个Socket表示
- 服务器端加入多线程机制后,就可以同时为多个用户提供服务
- UDP属于不可靠的连接协议,采用数据报的形式,服务器发送的信息,客户端不一定可以收到。