Socket
传输协议
UDP协议:用户数据报协议
- 面向无连接、不可靠、无序的数据
- 以数据报作为数据传输的载体
传输数据时,首先将要传输的数据定义成数据报(Datagram),在数据报中指明要达到的socket(主机地址和端口号),然后再将数据发出。
类:
DatagramPacket——表示数据报包
DatagramSocket——进行端到端通信
TCP协议:传输控制协议
- 面向连接、可靠、有序的数据流
- 以字节流的方式发送数据
类:
客户端——Socket类
服务端——ServerSocket类
socket
Socket:网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。
socket 通信模型
(1) 创建Socket;
(2) 打开连接到Socket的输入/出流;
(3) 按照一定的协议对Socket进行读/写操作;
(4) 关闭Socket.
建立连接,收发数字字符串
使用 Socket(套接字)进行不同的程序之间的通信
1. 服务端开启8888端口,并监听着,时刻等待着客户端的连接请求
2. 客户端知道服务端的ip地址和监听端口号,发出请求到服务端
客户端的端口地址是系统分配的,通常都会大于1024
一旦建立了连接,服务端会得到一个新的Socket对象,该对象负责与客户端进行通信。
注意: 在开发调试的过程中,如果修改过了服务器Server代码,要关闭启动的Server,否则新的Server不能启动,因为8888端口被占用了。
1 服务器
package socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
try {
// 创建服务端Socket,即ServerSocket
// 指定绑定的端口,并监听此端口
ServerSocket ss = new ServerSocket(8888);
// 在8888端口监听,看是否有请求过来
System.out.println("监听端口号:8888");
Socket s = ss.accept();
// 打开输入流
InputStream is = s.getInputStream();
// // 读取数字
// int msg = is.read();
// System.out.println(msg);
// is.close();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String info = null;
while((info = br.readLine()) != null){
System.out.println("客户端发来消息:" + info);
}
s.shutdownInput(); // 关闭输入流
br.close();
is.close();
s.close(); // 关闭与客户端的连接,但服务端还在运行,IO资源不会释放
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2 客户端
package socket;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) {
try {
// 连接到本机的8888端口
Socket s = new Socket("127.0.0.1", 8888);
//
OutputStream os = s.getOutputStream();
// // 写出数字
// os.write(110);
PrintWriter pw = new PrintWriter(os);
pw.write("用户名:admin,密码:123");
pw.flush();
s.shutdownInput(); // 关闭输出流
pw.close();
os.close();
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用Scanner
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
try {
// 连接到本机的8888端口
Socket s = new Socket("127.0.0.1", 8888);
//
OutputStream os = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
// 使用Scanner读取控制台的输入,并发送到服务端
Scanner sc = new Scanner(System.in);
String str = sc.next();
dos.writeUTF(str);
dos.close();
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果
监听端口号:8888
客户端发来消息:lizhongping
例:服务端和客户端互聊
服务端
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args) {
try {
// 创建服务端Socket,即ServerSocket
// 指定绑定的端口,并监听此端口
ServerSocket ss = new ServerSocket(8888);
// 在8888端口监听,看是否有请求过来
System.out.println("监听端口号:8888");
Socket s = ss.accept();
// 打开输入流
InputStream is = s.getInputStream();
DataInputStream dis = new DataInputStream(is);
OutputStream os = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
while (true) {
String msg = dis.readUTF();
System.out.println("收到客户端信息:" + msg);
Scanner sc = new Scanner(System.in);
String str = sc.next();
dos.writeUTF(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
try {
// 连接到本机的8888端口
Socket s = new Socket("127.0.0.1", 8888);
//
OutputStream os = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
InputStream is = s.getInputStream();
DataInputStream dis = new DataInputStream(is);
while (true) {
Scanner sc = new Scanner(System.in);
String str = sc.next();
dos.writeUTF(str);
String msg = dis.readUTF();
System.out.println("收到服务端信息" + msg);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
注:我们可以明显的注意到问题所在:由于单线程的缘故,同一时间,要么收信息,要么发信息,不能同时进行。需要通过【多线程】改进。