TCP使用Socket进行网络通信的过程:
- 服务器程序将一个套接字绑定到一个特定的端口,并通过此套接字等待和监听来自客户端的连接请求;
- 客户端根据服务器所在的主机名和端口向服务器发送连接请求;
- 如果一切正常,服务器接收连接请求,并获得一个新的绑定到不同端口地址的套接字;
- 客户端和服务器通过读写套接字进行通讯。
UDP使用Socket进行网络通信的过程
- UDP协议通信没有客户端(浏览器)/服务器模式,通信的双方是平等的;
- 每个UDP建立都有独立的端口号绑定。编程时对独立的一个端点编程,使其同时具有发送接收的方法;
- 与TCP协议编程不同,UDP收发数据不用I/O流。
基于TCP协议的Socket编程
TCP服务端:
1. 创建一个ServerSocket对象;
2. 调用accept()方法接收客户端请求;
3. 从Socket中获取I/0流;
4. 对I/0进行读写操作,完成与客户端的交互。
TCP客户端:
1. 创建一个Socket对象;
2. 从Socket中获取I/0流;
4. 对I/0进行读写操作,完成与客户端的交互;
5. 关闭I/O流和Socket。
服务器编程:接收客户端传来的字节流,转化成字符流,再转化成大写,传回服务器。
import java.net.ServerSocket;
public class TCPServer{
public static void main(String[] args){
//1.创建一个ServerSocket对象
ServerSocket serverSocket=new ServerSocket();
//2.调用accept()方法来接受客户端请求
Socket socket=serverSocket.accept();
System.out.println(socket.getInetAddress().getHostAddress()+"has connected");//表示某台网络设备与服务器连接成功
//3.从Socket对象中获取I/0流;
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
'''BufferedWriter bw=new BufferedWriter(new OutputSreamWriter(socket.getOutputStram()));'''
//自动刷新缓冲区
PrintWriter pw=new PrintWriter(socket.getOutputStream().true);
//把客户端传过来的字节流转换成字符流
String line=null;
while(line=br.readline()!=null){
if(line.equals("over")){
break;
}
System.out.println(line);
'''''
bw.write(line.toUpperCase());//把转换成大写的字符串传给客户端。
bw.newLine();//换行,标志着一段字符输入完毕,客户端readLine才会确认输入完毕
bw.flush();//清空缓冲区
'''''
pw.println(line.toUpperCase());
}
//释放资源
'''bw.close();'''
pw.close();
br.close();
socket.close();
System.out.println(socket.getInetAddress().getHostAddress()+"has disconnected");//表示某台网络设备与服务器连接断开
}
}
客户端编程:客户端传输键盘输入给服务器,再读取从服务器传回的大写字符串
import java.net.Socket;
public class TCPClient{
public static void main(String[] args) throws IOExceprion{
//1.创建一个Socket对象;
Socket socket=new Socket("127.0.0.1",);
//读取键盘输入的字节流
BufferedReader br=new BufferedReader(new InputStramReader(System.in));
//对I/0进行读写操作,完成与客户端的交互;
//把键盘输入的字节流存入socket的buffer中向服务器发送
BufferedWriter bw=new BufferedWriter(new OutputSreamWriter(socket.getOutputStram()));
//从socket的buffer中读取服务器传来的字节流
BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true){
String line=br.readLine();//从键盘不断输入的字符串
bw.write(line);
bw.newLine();//换行,标志着一段字符输入完毕,服务端readLine才会确认输入完毕
bw.flush;
if(line.equals("over")){
break;
}
//读取从服务端传来的字符
System.out.println(reader.readline());
}
//释放资源
reader.close();
br.close();
bw.close();
socket.close();
}
}
执行:分别打开两个DOS窗口,第一个先运行服务器程序,第二个运行客户端程序
基于UDP协议的Socket编程
创建发送端
1. 建立DatagramSocket对象,该端点建立,系统会随机分配一个端口,也可以手动指定;
2. 将数据进行packet包的封装,必须要指定目的地址和端口;
3. 通过socket服务的send方法将该包发出;
4. 将socket 关闭。
创建接收端
1. 建立DatagramSocket对象,要监听一个端口;
2. 通过socket的receive方法将获取数据包;
3. 通过数据包dp的方法 getData()、getAddress()、getPort()等方法,获取包中的信息;
4. 将socket关闭。
UDP端点编程:
发送端
import java.net InetAddress;
import java.net DatagramSocket;
import java.net DatagramPacket;
public class UDPDemo1{
public static void main(String[] args) throw IOException{
//1. 建立DatagramSocket对象,该端点建立,系统会随机分配一个端口;
DatagramSocket socket=new DatagramSocket();
//2. 发送数据,将数据进行packet包的封装,必须要指定目的地址和端口;
String str="I love studying";
DatagramPacket packet=new DatagramPacket(str.getBytes(),str.length,InetAddress.getByName("localhost"),);
//参数列表:【发送数据】【发送数据的长度】【接收端主机的地址】【接收端口号】
//3. 通过socket服务的send方法将该包发出;
socket.send(packet);
//4. 通过socket的receive方法将获取数据包,存入一个数组;
byte[] buff=new byte[];
DatagramPacket packet2=new DatagramPacket(buff,);
socket.receive(packet2);
//5.通过数据包dp的方法 getData()把接受的字节数组转换成字符串
System.out.println(new String(packet2.getData()));
//6. 将socket 关闭
socket.close();
}
}
接收端
import java.net InetAddress;
import java.net DatagramSocket;
import java.net DatagramPacket;
public class UDPDemo2{
public static void main(String[] args) throw IOException {
//1. 建立DatagramSocket对象,该端点建立,手动指定端口;
DatagramSocket socket=new DatagramSocket();
//2. 通过socket的receive方法将获取数据包,存入一个数组;
byte[] buff=new byte[];
'''''
DatagramPacket packet=new DatagramPacket(buff,100);
//当接收字符长度不够100时会出现多余的字符
'''''
DatagramPacket packet=new DatagramPacket(buff,,packet.getLength());
socket.receive(packet);
//3.通过数据包dp的方法 getData()把接受的字节数组转换成字符串
System.out.println(new String(packet.getData()));
//4. 发送数据,将数据进行packet包的封装,必须要指定目的地址和端口;
String str="Study makes my happy!";
DatagramPacket packet2=new DatagramPacket(str.getBytes(),str.length,packet.getAddress(),packet.getPort());
//【接收端主机的地址】【接收端口号】可以根据之前接收到的packet获取
//5. 通过socket服务的send方法将该包发出;
socket.send(packet2);
//6. 将socket 关闭
socket.close();
}
}