TCP/UDP
TCP和UDP同属于传输层协议,对比TCP和UDP:
UDP TCP
是否连接 无连接 面向连接
是否可靠 不可靠传输 可靠传输
连接个数 支持一对一,一对多,多对多通信 只能是一对一通信
传输方式 面向报文 面向字节流
适用场景 适用于实时应用(IP电话等) 适用于要求可靠传输的应用,例如文件传输
Socket编程
Socket基于TCP/IP协议,用于客户端和服务器端通信。
Socket
网络套接字,用于连接另一台计算机
创建方法:
new Socket("IP地址",端口号)
注意:一旦创建了Socket对象,就自动连接对方计算机
常用方法:
getInputStream() 获得输入流,读取对方发来的数据
getOutputStream() 获得输出流,给对方发数据
close() 关闭
注意:一旦输入流或输出流关闭,Socket连接会自动关闭。
ServerSocket
服务器端Socket,Socket的子类,用于接受客户端并和客户端通信
创建:
new ServerSocket(端口号)
注意:一旦创建ServerSocket对象,会不断侦听该端口,判断是否有客户端连接
主要方法:
Socket accept() 用于获得连接过来的客户端Socket对象
服务器端和客户端的通信
服务器端实现步骤:
创建ServerSocket对象
循环调用accept方法获得连接
调用Socket对象的IO流来读取、发送数据。
public class Server {
public static final int PORT = 8888;
public void start(){
System.out.println("启动服务器。。。");
//创建ServerSocket对象
try {
ServerSocket server = new ServerSocket(PORT);
//循环获得客户端连接
while(true){
Socket client = server.accept();
System.out.println(client.getInetAddress()+"连接了");
//获得客户端的输入流和输出流
try(DataInputStream dis = new DataInputStream(client.getInputStream());
DataOutputStream dos = new DataOutputStream(client.getOutputStream())){
//读取客户端的消息
System.out.println("客户端"+client.getInetAddress()+"说:"+dis.readUTF());
//给客户端发消息
dos.writeUTF("我是服务器端,客户端你好啊~~~~~~~~~~~~~~~~");
}catch(IOException ex){
ex.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Server().start();
}
}
客户端实现步骤:
- 创建Socket对象
- 调用Socket对象的getInputStream来读取数据。
- 调用Socket对象的getOutputStream来发送数据。
public class Client {
public void sendMessage(String ip,int port,String msg){
//创建Socket对象,连接服务器端
try {
Socket socket = new Socket(ip,port);
//获得输出流和输入流
try(DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
DataInputStream dis = new DataInputStream(socket.getInputStream())){
//发送数据给服务器端
dos.writeUTF(msg);
//读取服务器端的消息
System.out.println("服务器端说:"+dis.readUTF());
}catch(Exception ex){
ex.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Client().sendMessage("192.168.53.5", 8888,
"你好!!!服务器端");
}
}
环形链表
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
提示:
链表中节点的数目范围是 [0, 104]
-105 <= Node.val <= 105
pos 为 -1 或者链表中的一个 有效索引 。
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null){
return false;
}
Set<ListNode> visited = new HashSet<ListNode>();
ListNode curr = head;
while(curr != null){
if(visited.contains(curr)){
return true;
}else{
visited.add(curr);
}
curr = curr.next;
}
return false;
}
}