一、传输协议UDP和TCP
TCP是Tranfer Control Protocol的 简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建 立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送 或接收操作。
UDP是User Datagram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
比较:
1、UDP的传输数据有大小限制,且每个被传输是数据报限定在64kb之内。
2、UDP传输速率快,但是不可靠,TCP相反。
二、Socket编程
网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。一个Socket由一个IP地址和一个端口号唯一确定。在java开发环境下,Socket编程主要指基于TCP/IP协议的编程。
创建socket:
1、创建socket:
其构造方法有:
Socket(InetAddress address, int port);
Socket(InetAddress address, int port, boolean stream);
Socket(String host, int prot);
Socket(String host, int prot, boolean stream);
Socket(SocketImpl impl)
Socket(String host, int port, InetAddress localAddr, int localPort)
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
ServerSocket(int port);
ServerSocket(int port, int backlog);
ServerSocket(int port, int backlog, InetAddress bindAddr)
其中address、host和port分别是双向连接中另一方的IP地址、主机名和端 口号,stream指明socket是流socket还是数据报socket,localPort表示本地主机的端口号,localAddr和 bindAddr是本地机器的地址(ServerSocket的主机地址),impl是socket的父类,既可以用来创建serverSocket又可 以用来创建Socket。count则表示服务端所能支持的最大连接数。
三、通信的基本步骤:
服务器端:
1. 在服务器,用一个端口来实例化一个 ServerSocket对象。此时,服务器就可以这个端口时刻监听从客户端发来的连接请求。
2.调用ServerSocket的accept方法,开始监听连接从端口上发来的连接请求。
3.利用accept方法返回的客户端的Socket对象,进行读写IO的操作
4.通讯完成后,关闭打开的流和Socket对象。
Demo:必须先启服务
package com.xuzengqiang.socket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
@SuppressWarnings("all")
public class Server {
private static Integer port=8060;
public static void run() throws Exception {
BufferedReader read = null;
PrintWriter out = null;
ServerSocket server=new ServerSocket(port);
System.out.println("服务端启动............");
//一直处于阻塞状态,直到客户端连接
Socket socket=server.accept();
System.out.println("客户端与服务器建立连接!");
read = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
while(true){
Scanner input = new Scanner(System.in);
//接收客户端发送的数据
String message=read.readLine();
System.out.println(message);
//如果客户端发送的数据为"bye!".终止连接
if("bye!".equals(message)){
break;
}
out.println("管理员:" + input.nextLine());
}
out.close();
read.close();
socket.close();
server.close();
}
public static void main(String[] args) {
try {
run();
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端:
1.用服务器的IP地址和端口号实例化Socket对象。
2.调用connect方法,连接到服务器上。
3.将发送到服务器的IO流填充到IO对象里,比如BufferedReader/PrintWriter。
4.利用Socket提供的getInputStream和getOutputStream方法,通过IO流对象,向服务器发送数据流。
5. 通讯完成后,关闭打开的IO对象和Socket。
package com.xuzengqiang.socket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
@SuppressWarnings("all")
public class Client {
private static InetAddress ipAddress;
private static Integer port = 8060;
// 获取本机IP地址
static {
try {
ipAddress = InetAddress.getByName("localhost");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public static void start() throws Exception {
Socket socket = null;
BufferedReader read = null;
PrintWriter out = null;
socket = new Socket(ipAddress, port);
read = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
while (true) {
// 利用PrintWriter向服务器发送消息
Scanner input = new Scanner(System.in);
out.println("强哥:" + input.nextLine());
// 利用BufferedReader向服务器接收消息
String message = read.readLine();
System.out.println(message);
if ("bye!".equals(message)) {
out.println("bye!");
break;
}
}
//关闭流
out.close();
read.close();
socket.close();
}
public static void main(String[] args) {
try {
start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
多线程通信:上面的程序一个Server只能有一个Client,如果要一个Server可以与多个Client进行通信,可以利用线程。将处理流程放到一个独立的线程中去,然后等待下一个Client连接即可。
Server:服务器端
package com.xuzengqiang.udp.server.more;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
@SuppressWarnings("all")
public class ServerOne {
private static final Integer port = 8060;
public static void execute(final Socket socket) {
new Thread(new Runnable() {
@Override
public void run() {
BufferedReader read = null;
PrintWriter out = null;
try {
read = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
while (true) {
Scanner input = new Scanner(System.in);
// 接收客户端发送的数据
String message = read.readLine();
System.out.println(message);
out.println("管理员:" + input.nextLine());
out.flush();
// 如果客户端发送的数据为"bye!".终止连接
if ("bye!".equals(message)) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (read != null) {
read.close();
}
if (out != null) {
out.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
public static void main(String[] args) {
ServerSocket server;
try {
server = new ServerSocket(port);
System.out.println("服务端启动............");
while (true) {
// 一直处于阻塞状态,直到客户端连接
Socket socket = server.accept();
System.out.println("客户端与服务器建立连接!");
execute(socket);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client:客户端
package com.xuzengqiang.socket.more;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
@SuppressWarnings("all")
public class ClientTwo {
private static InetAddress ipAddress;
private static Integer port = 8060;
// 获取本机IP地址
static {
try {
ipAddress = InetAddress.getByName("localhost");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public static void start() throws Exception {
Socket socket = null;
BufferedReader read = null;
PrintWriter out = null;
socket = new Socket(ipAddress, port);
read = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
while (true) {
// 利用PrintWriter向服务器发送消息
Scanner input = new Scanner(System.in);
out.println("伍岳:" + input.nextLine());
// 利用BufferedReader向服务器接收消息
String message = read.readLine();
System.out.println(message);
if ("bye!".equals(message)) {
out.println("bye!");
break;
}
}
// 关闭流
out.close();
read.close();
socket.close();
}
public static void main(String[] args) {
try {
start();
} catch (Exception e) {
e.printStackTrace();
}
}
}