本文内容来自李兴华《java开发实战经典》,整理作为学习笔记。
1、TCP程序设计
在java中使用Socket(即套接字)完成TCP程序的开发,使用此类可以方便地建立可靠的、双向的、持续性的、点对点的通信连接。
主要用到的类为:ServerSocket和Socket
(1)第一个TCP程序
编写服务器端程序:
package com.lixinghua.demo;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class HelloServer
{
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException
{
// TODO Auto-generated method stub
ServerSocket server = null;//声明一个ServerSocket对象
Socket client = null;
PrintStream out =null;
server = new ServerSocket(8888);//此服务器在8888端口上等待客户端的访问
System.out.println("服务器运行,等待客户端连接");
client = server.accept();//程序阻塞,等待客户端连接
String string = "Hello World";
out = new PrintStream(client.getOutputStream());//实例化打印流对象,输出信息
out.println(string);
out.close();
client.close();
server.close();
}
}
编写客户端程序:
package com.lixinghua.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class HelloClient
{
/**
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException, IOException
{
// TODO Auto-generated method stub
Socket client = null;
client = new Socket("localhost",8888);//指定连接的主机和端口
BufferedReader buf = null;
buf = new BufferedReader(new InputStreamReader(client.getInputStream()));//取得客户端的输入流
String string = buf.readLine();//读取信息
System.out.println("服务器端输出内容:"+string);
client.close();
buf.close();
}
}
2、经典案例:Echo(应用多线程)
Echo程序时一个网路编程通信交互的一个经典案例,称为回应程序,即客户端输入哪些内容,服务器会在这些内存前加上“ECHO:”,并将信息发回给客户端。
(1)客户端程序:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class EchoClient
{
/**
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException, IOException
{
// TODO Auto-generated method stub
Socket client = null;
client = new Socket("localhost",8888);
BufferedReader buf = null;
PrintStream out = null;
BufferedReader input = null;
input = new BufferedReader(new InputStreamReader(System.in));//从键盘接受数据
out = new PrintStream(client.getOutputStream());//向服务器端发送信息
buf = new BufferedReader(new InputStreamReader(client.getInputStream()));//接受服务器端输入信息
boolean flag = true;//定义标志位
while (flag)
{
System.out.println("输入信息:");
String string = input.readLine();
out.println(string);
if("bye".equals(string))
{
flag = false;
}else {
String echo = buf.readLine();
System.out.println(echo);
}
}
client.close();
buf.close();
}
}
(2)服务器端的程序。
a)继承Runnable接口
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class EchoThread implements Runnable
{
public Socket client = null;
public EchoThread(Socket client)
{
this.client = client;//通过构造方法设置Socket
}
@Override
public void run()
{
// TODO Auto-generated method stub
PrintStream out = null;//定义输出流
BufferedReader buf = null;//用于接受客户端发送来的信息
try
{
buf = new BufferedReader(new InputStreamReader(client.getInputStream()));//得到客户端输入的信息
out = new PrintStream(client.getOutputStream());//实例化客户端的输出流
boolean flag = true;
while (flag)
{
String string = buf.readLine();
if(string==null||"".equals(string))
{
flag = false;
}else {
if("bye".equals(string))
{
flag = false;
}else {
out.println("ECHO:"+string);
}
}
}
out.close();
client.close();
} catch (Exception e)
{
// TODO: handle exception
}
}
}
b)服务器端主程序
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Echo
{
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException
{
// TODO Auto-generated method stub
ServerSocket server = null;
Socket client = null;
server = new ServerSocket(8888);//此服务器在8888端口上监听
boolean f = true;
while (f)
{
System.out.println("服务器运行,等待客户端连接。");
client = server.accept();//接受客户端连接
new Thread(new EchoThread(client)).start();//实例化并启动一个线程对象
}
server.close();
}
}
3、上述程序的效果如图:
(1)服务器启动
(2)三个客户端启动
4、UDP程序设计
使用UDP发送的消息,对方不一定会接受到。所有的信息使用数据报的形式发送出去,所以这就要求客户端始终等待接受服务器发送过来的消息,在java中使用DatagramSocket类和DatagramPacket类完成UDP程序的开发。
(1)UDP客户端
import java.net.*;
public class UDPClient
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds = null;
byte[] buf = new byte[1024];//定义接收数据的字节数组
DatagramPacket dp = null;
ds = new DatagramSocket(9000);//此客户端在9000端口监听
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();
}
}
(2)UDP服务器端
import java.net.*;
public class UDPServer
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds = null;
DatagramPacket dp = null;
ds = new DatagramSocket(3000);//服务器在3000端口监听
String str = "Hello world";//准备好要发送的数据
//实例化DatagramPacket对象,指定数据内容,数据长度,要发送的目标地址,发送端口
dp = new DatagramPacket(str.getBytes(),str.length(),InetAddress.getByName("localhost"),9000);
System.out.println("发送消息:");
ds.send(dp);//发送数据报
ds.close();
}
}
(3)结果如图: