socket编程可以理解为是一种二进制+IP+端口的一种通讯模式,在任何语言中,都有socket编程,因此几乎所有语言的socket都可以互通。只要是涉及到通讯方面的如QQ,微信等都是涉及到socket,只是他们自己进行了封装。socket的本质是对tcp/ip的封装。
网络通讯:
UDP:是面向无连接的,所以效率较高,不会建立连接,不安全。不管有没有接收方,只管向指定地址发送东西。(但要求大小在64k以内)底层使用UDP协议。
TCP:是面向连接的,三次握手成功之后才能通讯,字节流传输,效率低于UDP,但是安全性高(因为采用了三次握手和四次挥手协议)。双方需要建立连接才能通讯(发送数据)。底层使用TCP协议,TCP底层是用HTTP协议。
TCP三次握手四次挥手示意图:
TCP通讯实现:
先创建服务器端:
//TCP协议服务端
public class Server {
public static void main(String[] args) throws IOException {
System.out.println("TCP服务端启动了");
//启动服务端
ServerSocket serverSocket = new ServerSocket(8080);//传入端口号
//等待客户端连接(如果客户端不连接进来,程序一直阻塞在这里等待)
Socket accept = serverSocket.accept();
//模拟客户端给服务端发送消息的场景
//生成输入流
InputStream is = accept.getInputStream();
//定义字节
byte [] bytes = new byte[1024];
//读取
int length = is.read(bytes);
//将byte数组转为String
String result = new String(bytes, 0, length);
System.out.println("服务器端已经接收到客户端发送的消息:"+result);
}
}
TCP客户端:
//TCP客户端
public class TCPClient {
public static void main(String[] args) throws Exception, IOException {
//创建socket
Socket socket = new Socket("127.0.0.1", 8080);//传入IP和端口号
//创建输出流
OutputStream os = socket.getOutputStream();
//先定义一段话
String mes = "hello";
//发送
os.write(mes.getBytes());
System.out.println("客户端发送消息完毕");
}
}
先运行服务器端:
运行客户端:
消息发送完成后,我们再看服务端打印的内容:
下面我们继续写一下服务器接收到消息后的反馈,服务器端:
//TCP协议服务端
public class Server {
public static void main(String[] args) throws IOException {
//启动服务端
ServerSocket serverSocket = new ServerSocket(8080);
try {
System.out.println("TCP服务端启动了");
//等待客户端连接(如果客户端不连接进来,程序一直阻塞在这里等待)
Socket accept = serverSocket.accept();
//模拟客户端给服务端发送消息的场景
//生成输入流
InputStream is = accept.getInputStream();
//定义字节
byte [] bytes = new byte[1024];
//读取
int length = is.read(bytes);
//将byte数组转为String
String result = new String(bytes, 0, length);
System.out.println("服务器端已经接收到客户端发送的消息:"+result);
//返回消息
//得到一个OutputStream
OutputStream outputStream = accept.getOutputStream();
//将输出流转为打印流
PrintWriter pw = new PrintWriter(outputStream);
pw.print("我是服务器,已经收到消息");
pw.flush();
accept.shutdownOutput();
} catch (Exception e) {
// TODO: handle exception
}finally {
//使用try,万一代码出现异常,我们就在finally中关闭连接
serverSocket.close();
}
}
}
客户端:
//TCP客户端
public class TCPClient {
public static void main(String[] args) throws Exception, IOException {
//创建socket
Socket socket = new Socket("127.0.0.1", 8080);//传入IP和端口号
try {
//创建输出流
OutputStream os = socket.getOutputStream();
//先定义一段话
String mes = "hello";
//发送
os.write(mes.getBytes());
System.out.println("客户端发送消息完毕");
//获取服务端发送的消息
//获取InputStream
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//读
String result = br.readLine();
System.out.println("客户端===》》服务器返回的结果:"+result);
} catch (Exception e) {
}finally {
socket.close();
}
}
}
先运行服务端:
再运行客户端:
此时再看服务端:
UDP实现:
先创建UDP服务端:
//UDP服务端
public class UdpServer {
public static void main(String[] args) throws IOException {
System.out.println("udp服务启动了");
//定义DatagramSocket
DatagramSocket ds = new DatagramSocket(8080);//不传地址,默认本级
//创建接收的数组
byte [] buf = new byte[1024];
//获取客户端发送的数据
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//直到有客户端连接起来,程序才会执行下去,否则一直阻塞在这里
ds.receive(dp);
String string = dp.getAddress().toString();
String data = new String(dp.getData(),0,dp.getLength());
System.out.println("服务器接收从IP:"+string+"传输的数据"+data);
}
}
创建UDP客户端:
//udp客户端
public class UdpClient {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();//此处不用传参数
//定义发送的数据
String mes = "hello";
byte[] bytes = mes.getBytes();
DatagramPacket dp = new DatagramPacket(bytes, bytes.length,new InetSocketAddress("127.0.0.1",8080));
//发送数据
ds.send(dp);
ds.close();
System.out.println("客户端发送信息完毕");
}
}
先启动服务端:
再启动客户端:
再看服务端:
下面我们来验证一下UDP是无连接的,发送消息时不会关心服务端是否在。我们关掉服务端,启动客户端,此时不会出现异常错误,即验证上述。然后我们关掉服务端和客户端,再重新启动服务端和客户端时,刚才在服务端没有启动时发送的数据已经被覆盖掉了,所以服务端接收到的是它启动之后的数据。