前言:
而今各位老铁们对“java socket接口开发”大致比较关注,我们都需要分析一些“java socket接口开发”的相关文章。那么小编在网上网罗了一些有关“java socket接口开发””的相关资讯,希望各位老铁们能喜欢,姐妹们一起来了解一下吧!作者:zskingking
博客:
上周我们描述了传输层协议TCP、UDP,但它们毕竟只是协议,看不见摸不着,那我们怎们通过TCP、和UDP进行实际传输呢?不用着急,等看完这篇文章你一定会明白的。
Socket概述
Socket中文意思为插座的意思,专业术语称之为套接字,它把TCP/IP封装成了调用接口供开发者调用,也就是说开发者可以通过调用Socket相关API来实现网络通讯。在Java中也存在Socket相关API,主要分为两个,分别是基于UDP传输协议的Socket和基于TCP传输协议的Socket,本篇文章会对基于这两种传输协议的Socket进行详细描述。
UDP Socket
通过上节的内容我们知道UDP是无连接的,只要提供对方的IP地址和端口号就能进行数据的传输,其中IP负责定位主机端口负责定位应用。知道了目标IP和目标端口号通过Java中的UDP Socket就能进行IO传输,我们来看一下具体的代码体现
*** 发送方UDP
*/
public class UDPSocketSend {
public static void main(String[] args) throws IOException {
System.out.println("Sender Start...");
//1.创建socket服务
DatagramSocket ds = new DatagramSocket;
//2.封装数据
String str = "Did you recite words today";
byte bytes = str.getBytes;
//地址
InetAddress address =InetAddress.getByName("192.168.31.137");
//参数:数据、长度、地址、端口
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,6666);
//3.发送数据包
ds.send(dp);
//4.关闭socket服务
ds.close;
}
/**
* 接收方UDP
*/
public class UDPSocketReceive{
public static void main(String[] args) throws IOException {
System.out.println("Receiver Start...");
//1.创建udp的socket服务,并声明端口号
DatagramSocket ds = new DatagramSocket(6666);
//2.创建接收数据的数据包
byte bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
//3.将数据接收到数据包中,为阻塞式方法
ds.receive(dp);
//4.解析数据
InetAddress address = dp.getAddress;//发送方IP
int port = dp.getPort;//发送方端口
String content = new String(dp.getData,0,dp.getLength);
System.out.println("address:"+address+"---port:"+port+"---content:"+content);
//关闭服务
ds.close;
}
}
分别启动发送方和接收方,我们来看一下打印结果
发送方:
Sender Start...
接收方:
Receiver Start...address:/192.168.31.137---port:65037---content:Did you recite words today
成功接收到消息,并打印出发送方IP和端口,下面我来个大家撸一遍步骤
发送方:
首先创建udp的socket服务
将需要发送的数据放在数据包DatagramSocket中,DatagramSocket会根据UDP协议对数据包、IP、端口号进行封装
通过udp的socket服务将数据包发送
最后将udp服务关闭
接收方:
创建udp的socket服务,并且明确自己的端口号
创建DatagramSocket用来解析数据接收到的数据包
将数据接收到数据包DatagramSocket中
通过DatagramSocket解析数据
关闭服务
整个UDP发送数据的流程就是这样
注意点:
为UDP是无连接的不可靠传输,所以接收方需要在发送方发送数据之前就启动,否则会接收不到数据,也就是说必须先运行UDPSocketReceive再运行UDPSocketSend。
聊天实例
把上面的例子进行一些小改动就可以实现聊天功能
public class UDPSocket1 {public static void main(String[] args) {
try {
new Thread(new Runnable {
@Override
public void run {
try {
receive;
} catch (IOException e) {
e.printStackTrace;
}
}
}).start;
send;
} catch (IOException e) {
e.printStackTrace;
}
}
//接收消息方法
private static void receive throws IOException {
System.out.println("UDOSocket1 Receiver Start...");
//1.创建udp的socket服务,并声明端口号
DatagramSocket ds = new DatagramSocket(6666);
//无限循环,一直处于接收状态
while (true) {
//2.创建接收数据的数据包
byte bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//3.将数据接收到数据包中
ds.receive(dp);
//4.解析数据
String content = new String(dp.getData, 0, dp.getLength);
System.out.println("UDPSocket1 Receive:" + content);
}
}
private static void send throws IOException {
//1.创建socket服务
DatagramSocket ds = new DatagramSocket;
//将键盘输入的信息转换成输入流再放入到缓冲区
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = ;
while ((line=br.readLine)!=){
//2.封装数据
byte bytes = line.getBytes;
//地址
InetAddress address =InetAddress.getByName("192.168.31.137");
//参数:数据、长度、地址、端口
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,7777);
//3.发送数据包
ds.send(dp);
}
//4.关闭socket服务
ds.close;
}
}
public class UDPSocket2 {
public static void main(String[] args){
try {
new Thread(new Runnable {
@Override
public void run {
try {
receive;
} catch (IOException e) {
e.printStackTrace;
}
}
}).start;
send;
} catch (IOException e) {
e.printStackTrace;
}
}
//接收消息方法
private static void receive throws IOException {
System.out.println("UDOSocket2 Receiver Start...");
//1.创建udp的socket服务,并声明端口号
DatagramSocket ds = new DatagramSocket(7777);
//无限循环,一直处于接收状态
while (true) {
//2.创建接收数据的数据包
byte bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//3.将数据接收到数据包中
ds.receive(dp);
//4.解析数据
String content = new String(dp.getData, 0, dp.getLength);
System.out.println("UDPSocket2 Receive:" + content);
}
//关闭服务
// ds.close;
}
private static void send throws IOException {
//1.创建socket服务
DatagramSocket ds = new DatagramSocket;
//将键盘输入的信息转换成输入流再放入到缓冲区
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = ;
while ((line=br.readLine)!=){
//2.封装数据
byte bytes = line.getBytes;
//地址
InetAddress address =InetAddress.getByName("192.168.31.137");
//参数:数据、长度、地址、端口
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,6666);
//3.发送数据包
ds.send(dp);
}
//4.关闭socket服务
ds.close;
}
}
在接收方方法写一个无限循环让其处于持续接收状态,发送发通过对键盘录入加回车进行消息的发送,并且两个端点都具备发送和接收功能。需要注意的是receive会执行一个无限循环,所以receive和send必须位于不同线程,否则会导致无法发送消息从而也接收不到消息。
来看打印结果:UDPSocket1
UDPSocket Receiver Start...UDPSocket Receive:hello udp1
heelo udp2
UDPSocket2
UDPSocket2 Receiver Start...hello udp1
UDPSocket2 Receive:hello udp2
我在UDPSocket1 的控制台中输入了:“hello udp2”、在UDPSocket2 的控制台中输入了:“hello udp1”,接收内容和发送内容完全一致,一个简单的聊天功能就实现了,希望不熟悉的朋友也可以敲一遍代码练一遍。
TCP Socket
TCP基于client-server是面向连接的可靠传输,上篇文章我们也讲解了TCP安全传输机制,可谓是相当复杂,如果需要个人对TCP协议进行封装显然大多数开发者是很难实现的,所以Java也为开发者提供了基于TCP的Socket,不同于UDP,TCP Socket分为Socket和ServerSocket对应着client和server,下面我来用代码实现一个简单的TCP通讯功能:
客户端:
//客户端public class TCPClient {
public static void main(String[] args) throws IOException {
//1.创建TCP客户端Socket服务
Socket client = new Socket;
//2.与服务端进行连接
InetSocketAddress address = new InetSocketAddress("192.168.31.137",10000);
client.connect(address);
//3.连接成功后获取客户端Socket输出流
OutputStream outputStream = client.getOutputStream;
//4.通过输出流往服务端写入数据
outputStream.write("hello server".getBytes);
//5.关闭流
client.close;
}
}
首先创建一个Socket和InetSocketAddress ,然后通过Socket的connect方法进行连接,连接成功后可以获取到输出流,通过该输出流就可以向服务端传输数据。
服务端:
public class TCPServer {public static void main(String[] args) throws IOException {
//1.创建服务端Socket并明确端口号
ServerSocket serverSocket = new ServerSocket(10000);
//2.获取到客户端的Socket
Socket socket = serverSocket.accept;
//3.通过客户端的Socket获取到输入流
InputStream inputStream = socket.getInputStream;
//4.通过输入流获取到客户端传递的数据
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = ;
while ((line = bufferedReader.readLine)!=){
System.out.println(line);
}
//5.关闭流
socket.close;
serverSocket.close;
}
首先创建一个服务端Socket并明确端口号,通过accept方法获取到链接过来的客户端Socket,从客户端Socket中获取输入流,最后由输入流读取客户端传输来的数据。
我们来看看服务端的打印结果:
hello server
成功接收到客户端发来的数据
注意点:
一个服务端是可以同时和多个客户端进行通信的,那么它是如何区分不同客户端呢?从上面代码我们可以看到,服务端首先通过accept获取到客户端Socket,然后通过客户端的Socket获取的流进行通讯,这也让服务端得以区分每个客户端。
文件传输实例
流程:客户端上传一个文件到服务端,服务端收到文件后进行保存,保存成功后给客户端一个响应。
客户端代码
public class TCPUploadClient {public static void main(String[] args) throws IOException {
//1.创建TCP客户端Socket服务
Socket client = new Socket;
//2.与服务端进行连接
InetSocketAddress address = new InetSocketAddress("192.168.31.137",10001);
client.connect(address);
//3.读取客户端文件
FileInputStream fis = new FileInputStream("E://girl.jpg");
//4.获取输出流
OutputStream outputStream = client.getOutputStream;
//5.将文件写入到服务端
byte bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes))!=-1){
outputStream.write(bytes,0,len);
}
//6.通知服务器数据写入完毕
client.shutdownOutput;
//7.读取服务端响应的数据
InputStream inputStream = client.getInputStream;
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String line = br.readLine;
System.out.println(line);
//8.关闭流
inputStream.close;
fis.close;
client.close;
}
}
创建Socket并连接,读取本地文件输入流,将文件写入到服务端,写入成功后读取服务端返回的数据。
服务端代码
public class TCPUploadServer {public static void main(String[] args) throws IOException {
//1.创建客户端Socket
ServerSocket serverSocket = new ServerSocket(10001);
//2.获取到客户端Socket
Socket socket = serverSocket.accept;
//3.通过客户端Socket获取到输入流
InputStream is = socket.getInputStream;
//4.将流以文件的形式写入到磁盘
File dir = new File("F://tcp");
//如果文件夹不存在就创建文件夹
if(!dir.exists){
dir.mkdirs;
}
File file = new File(dir,"girl.jpg");
FileOutputStream fos = new FileOutputStream(file);
byte bytes = new byte[1024];
int len = 0;
while ((len = is.read(bytes))!=-1){
fos.write(bytes,0,len);
}
//5.通知客户端文件保存完毕
OutputStream os = socket.getOutputStream;
os.write("success".getBytes);
//6.关闭流
fos.close;
os.close;
socket.close;
}
}
创建Socket并获取到客户端Socket和输入流,在F盘的tcp目录下创建一个文件,将从客户端读取到的数据输出到文件中,保存成功后给客户端返回''success''
这样我们就实现了一哥客户端上传文件的功能,还是比较简单的,希望大家也能够跟着代码敲一遍。
TCP Socket多线程应用
细心的同学可能已经发现,上面我们的实例中一个服务端只能接收一个客户端的一次请求,这显然是不符合实际的,那么如何使一个服务端同时服务多个客户端呢?接着撸代码
//客户端1public class TCPClient1 {
public static void main(String[] args) throws IOException {
System.out.println("TCPClient1 Start...");
//1.创建TCP客户端Socket服务
Socket client = new Socket;
//2.与服务端进行连接
InetSocketAddress address = new InetSocketAddress("192.168.31.137",10004);
client.connect(address);
//3.连接成功后获取客户端Socket输出流
OutputStream outputStream = client.getOutputStream;
//4.通过输出流往服务端写入数据
outputStream.write("Hello my name is Client1".getBytes);
//5.告诉服务端发送完毕
client.shutdownOutput;
//6.读取服务端返回数据
InputStream is = client.getInputStream;
byte bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//7.关闭流
client.close;
}
}
//客户端2
public class TCPClient2 {
public static void main(String[] args) throws IOException {
System.out.println("TCPClient2 Start...");
//1.创建TCP客户端Socket服务
Socket client = new Socket;
//2.与服务端进行连接
InetSocketAddress address = new InetSocketAddress("192.168.31.137",10004);
client.connect(address);
//3.连接成功后获取客户端Socket输出流
OutputStream outputStream = client.getOutputStream;
//4.通过输出流往服务端写入数据
outputStream.write("Hello my name is Client2".getBytes);
//5.告诉服务端发送完毕
client.shutdownOutput;
//6.读取服务端返回数据
InputStream is = client.getInputStream;
byte bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//7.关闭流
client.close;
}
}
//服务端
public class TCPServer {
public static void main(String[] args) throws IOException {
receive;
}
private static void receive throws IOException {
System.out.println("Server Start...");
//创建服务端Socket并明确端口号
ServerSocket serverSocket = new ServerSocket(10004);
while (true){
//获取到客户端的Socket
Socket socket = serverSocket.accept;
//通过客户端的Socket获取到输入流
InputStream is = socket.getInputStream;
//通过输入流获取到客户端传递的数据
byte bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//将客户端发来的数据原封不动返回
OutputStream os = socket.getOutputStream;
os.write(new String(bytes,0,len).getBytes);
//关闭连接
socket.close;
}
}
}
客户端1控制台
TCPClient1 Start...Hello my name is Client1
客户端2控制台
TCPClient2 Start...Hello my name is Client2
这样就可以实现一个服务端服务多个客户端
细心的同学可能又发现了,上面的写法是存在问题的,由于服务端始终都在主线程中处理请求,所以客户端的请求需要被服务端排队处理,举个例子:Client1对服务端进行了一次请求,服务端在响应Client1之前是不会接受其他请求的,显然这是不符合逻辑的,真正的服务器是要具备并发处理的。而多线程恰好能解决这个问题,我们来看修改之后的服务端代码
public class TCPServer {public static void main(String[] args) throws IOException {
receive;
}
private static void receive throws IOException {
System.out.println("Server Start...");
//创建服务端Socket并明确端口号
ServerSocket serverSocket = new ServerSocket(10004);
while (true){
//获取到客户端的Socket
final Socket socket = serverSocket.accept;
//通过线程执行客户端请求
new Thread(new Runnable {
@Override
public void run {
try {
//通过客户端的Socket获取到输入流
InputStream is = socket.getInputStream;
//通过输入流获取到客户端传递的数据
byte bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//将客户端发来的数据原封不动返回
OutputStream os = socket.getOutputStream;
os.write(new String(bytes,0,len).getBytes);
//关闭连接
socket.close;
} catch (IOException e) {
e.printStackTrace;
}
}
}).start;
}
}
}
运行效果适合加线程之前是一样的,但这种方式效率更高。
本篇文章叙述了基于UDP和TCP的Socket,UDP是无连接的,所以UDP Socket在发送数据的时候只需要目标IP和端口即可发送。TCP是面向连接的并且是基于client-server模式,在传输数据前需要进行连接,可以通过多线程技术实现并发处理客户端请求。本篇文章内容还是比较简单的,希望大家能把文章中代码自己敲一遍,掌握Socket的同时也能让你自己UDP和TCP的理解更加深刻。
近期文章:
Android;UI开发神兵利器—Kotlin Anko
“微信,我想和你聊聊?” “不,你不想!”
快播CEO王欣发布社交产品,遭微信封杀!
今日问题:
大家都买好过年回家的车票没有?
打卡格式:
打卡 X 天,答:xxx 。
标签: #java socket接口开发 #socket编程怎么运行