套接字编程TCP/UDP:
在java里面有专门的类负责客户端和服务端通信的任务,而通信的种类有两种:TCP和UDP,TCP是典型的服务端/客户端模型,他通过客户端和服务端的连接,使用java IO流来达到效果。而在UDP中,我们用到的是数据报来进行通信。tcp通信需要建立专门的连接通道,通过这个通道进行通信,udp则是以数据报的接收发送达到通信效果。二者的区别在于是否需要建立通信通道。举个简单的例子:TCP通信就相当于是打电话,你给别人打电话,你需要知道别人的电话号码,就相当于IP地址。电话打通后,拨打电话的双方之间就是有信号通道,互相之间能听到对方说的话,一旦电话挂断,通信通道销毁,这个时候你就什么也听不到了。这个时候你就会想能不能发短信呢,当然能,UDP就相当于发送短信,我只需要知道对方的电话号码,直接编辑短信发给他就是了,不再需要建立专门的通道哦,但是UDP有一个明显的缺点就是消息不及时,手机收到短信几天甚至十几天过后才看到是常有的事,所以UDP的缺点就在于不能及时让对方知道,甚至对方可能接收不了。但是两种通信方式在实际编程中互相结合使用,互相弥补优缺点。
TCP:
tcp中涉及到的主要有两个类:Socket
和ServerSocket,Socket
用于客户端,ServerSocket用于服务端。
Socket的用法:Socket socket = new Socket(ip,port);
最常用的构造方法之一,含义是连接到地址为ip的服务器上,端口为port.一般socket通信使用IO流来进行写入和读取,客户端向流里面写东西,socket通过调用getInputStream()
和getOutputStream()
方法来获取输出输入流,服务端从流里面把数据读取出来过后又向流里面写入东西,客户端再从流里面读取信息,完成一次对话:
BufferedWriter bw = new BufferedWriter(new InputStreamWriter(socket.getOutpouStream()));
bw.write("hello world");
//一定要加这句话,将缓冲区的内容全部排出
bw.fllush();
`ServerSocket`用法:`ServerSocket serversocket = new ServerSocket(port)`;建立监听窗口,等待连接:
//发方法在没有接收到客户端的连接请求时一直处于阻塞状态,返回值是Socket
Socket socket = serversocket.accept();
//建立输入流,读取客户端发来的信息
`BufferedReader br = new BufferedReader(new`
InputStreamReader(socket.getInputStream()));
byte[] buf = new byte[2048];
//调用read方法,将流里面的内容读取到byte数组中,并返回其长度
int len = in.read(buf);
//将byte数组转换为字符串
System.out.println(new String(buf,0,len) );
再向客户端写东西:
BufferedReader bo= new BufferedWriter(new InputStreamWriter(socket.getOutputStream()));
String s = "客户你好,我已收到消息";
bo.write(s);
在客户端里再用BufferedReader将信息读取出来即可.
下面用具体例子给大家讲解:
客户端:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
private int port;
private String address;
private Socket socket;
private BufferedWriter out;
private BufferedReader in;
public Client(int port,String address){
this.port = port;
this.address = address;
}
public void start() throws UnknownHostException, IOException{
//发送连接请求
socket = new Socket(address,port);
//输入流
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//向流里面输入内容
out.write("快来和我聊天吧");
out.flush();
System.out.println("向服务端发送数据:");
try{
//while的作用是能一直从键盘读入
while(true){
//不要用readLine()该方法容易引起阻塞
char[] cbuf = new char[2048];
int len = in.read(cbuf);
System.out.println("收到服务端回话:"+new String(cbuf,0,len));
Scanner scan = new Scanner(System.in);
String s = scan.next();
if(!s.equals("再见")){
out.write(s);
out.flush();
}else{
socket.close();
in.close();
out.close();
socket.close();
}
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
System.out.println("所有连接已关闭");
}catch(Exception e){
e.printStackTrace();
}
}
}
public static void main(String[] args) throws UnknownHostException, IOException{
Client client = new Client(9994,"127.0.0.1");
client.start();
}
}
服务端:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Service {
private BufferedReader in;
private BufferedWriter out;
private ServerSocket serversocket;
private Socket socket;
private int port;
public Service(int port){
this.port = port;
}
public void response() throws IOException, InterruptedException{
try {
//建立监听端口
serversocket = new ServerSocket(this.port);
System.out.println("准备接收客户端发来的数据:");
//阻塞,等待客户端发请求
socket = serversocket.accept();
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
System.out.println("连接成功,客户端信息:"+socket);
//为客户端开一个新线程
try{
while(true){
char[] cbuf = new char[2048];
int len = in.read(cbuf);
System.out.println("收到客户端消息:"+new String(cbuf,0,len));
//out.write("我已经给你连接上了,开始聊天吧");
//必须要用上out.flush,不然数据在缓冲区中,不能被读取
//out.flush();
Scanner scan = new Scanner(System.in);
String s = scan.next();
if(!s.equals("再见")){
out.write(s);
out.flush();
}else{
serversocket.close();
in.close();
out.close();
socket.close();
}
}
}catch(Exception e){
e.printStackTrace();
}
//向客户端发送内容
//建议不要用nextLine,因为该方法读取的是行,如果没读取到换行符,则会一直读下去,造成阻塞
} catch (IOException e) {
e.printStackTrace();
}
}
/*public class LogicThread extends Thread{
private BufferedReader in;
private BufferedWriter out;
private ServerSocket serversocket;
private Socket socket;
public LogicThread(BufferedReader in,BufferedWriter out,Socket socket,ServerSocket serversocket){
this.in = in;
this.out = out;
this.socket = socket;
this.serversocket = serversocket;
}
public void run(){
while(true){
}
}
}*/
public static void main(String[] args) throws IOException, InterruptedException{
Service service = new Service(9994);
service.response();
//service.serversocket.close();
}
}
UDP编程:
客户端:
DatagramSocket:套接字,相当于电话,使用方法:
DatagramSocket ds = new DatagramSocket();可以不需要绑定任何地址,因为你发送短信给别人的时候,任何手机都可以用,你只需要在发送短信的时候记住电话号码就行了
DatagramPacket:数据报,相当于短信,使用方法:
String s = "heelo world";
byte[] buf = s.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,Ip,port);
上面的IP就相当于电话号码,长度就是短信大小。
然后用电话把短信发出去:ds.send(dp);
服务端:
服务端需要建立监听端口,如果你手机关机别人是接收不到的,所以开机监听:
DatagramSocket ds = new DatagramSocket(port);
接收:
byte[] buf = new btye[2048]
//构造数据报
DatagramPacket dp = new DatagramPacket(buf,buf.length);
将收到的内容放到dp中
ds.receive(dp);
读取:
byte[] buf1 = dp.getData();
System.out.println(new String(buf1,0,buf1.length()));
返回结果给客户端:
String s = "收到";
byte[] buf2 = s.getBytes();
//通过接收到的数据报获得客户端的ip和port,并向他返回信息
ds.send(buf2,buf2.length,dp.getAddress(),dp.getPort());
客户端再通过receive()方法收到服务端返回的消息即可完成一次通信。
实例:
客户端:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
private int port;
private InetAddress address;
//发送报文给服务端
private DatagramPacket send;
//接收服务端发送过来的报文
private DatagramPacket recieve;
private DatagramSocket socket;
public Client(int port,InetAddress address){
this.port = port;
this.address = address;
}
public void send() {
//不需要绑定具体的发送地点,类似于邮局,你不需要在固定的邮局寄东西,所以这不绑定ip都可以,信封上有就行了
try{
socket = new DatagramSocket();
//发送
Scanner scan = new Scanner(System.in);
while(true){
String s = scan.next();
//将字符串转换到byte类型的buf数组里面
byte[] buf = s.getBytes();
send = new DatagramPacket(buf,buf.length,address,port);
socket.send(send);
System.out.println("发送成功,等待服务端响应");
//接收
byte[] rbuf = new byte[2048];
recieve = new DatagramPacket(rbuf,rbuf.length);
//未收到服务端消息时阻塞
socket.receive(recieve);
//用于接收
byte[] rbuf1 = recieve.getData();
int len = rbuf1.length;
System.out.println("服务端说:"+new String(rbuf1,0,len));
}
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) throws UnknownHostException{
Client client = new Client(9998,InetAddress.getByName("127.0.0.1"));
client.send();
}
}
服务端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Scanner;
public class Service {
private int port;
private DatagramPacket send;
private DatagramPacket recieve;
private DatagramSocket socket;
public Service(int port){
this.port = port;
}
public void recieve() throws IOException{
//建立监听窗口
socket = new DatagramSocket(port);
System.out.println("服务器已经启动");
//开启新线程为客户端处理事务
new LogicThread(recieve,socket);
//System.out.println("发送成功");
}
public class LogicThread extends Thread{
public DatagramPacket recieve;
public DatagramSocket socket;
public LogicThread(DatagramPacket recieve,DatagramSocket socket){
this.recieve = recieve;
this.socket = socket;
start();
}
public void run(){
try{
//while的作用是一直接接收数据包
while(true){
byte[] rbuf = new byte[2048];
//封装数据报,用于接收数据
recieve = new DatagramPacket(rbuf,rbuf.length);
//等待客户端发来数据,不然阻塞
socket.receive(recieve);
byte[] buf = recieve.getData();
int len = buf.length;
System.out.println("客户端发来数据:"+new String(buf,0,len));
//向客户端发送数据
Scanner scan = new Scanner(System.in);
String s = scan.next();
byte[] sbuf = s.getBytes();
send = new DatagramPacket(sbuf,sbuf.length,recieve.getAddress(),recieve.getPort());
socket.send(send);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException{
Service service = new Service(9998);
service.recieve();
}
}
简单的TCP/UDP通信介绍到此,如果有什么不对的大家尽量指出,这样才能共同进步,对吗。