socket编程的简单实现

socket编程是作为程序员必须会的,所以这篇博客就专门来讲一讲socket编程的基本实现。

话不多说,直接上实例,然后再分析讲解。

TCP版:

client端:

package day01;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class Client {
	public static void main(String[] args) {
		try {
			Socket socket=new Socket("127.0.0.1",4700);
                        //用户的输入
			BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
                        //写到服务器的输出流
			PrintWriter os=new PrintWriter(socket.getOutputStream());
                        //从服务器过来的输入流
			BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
			System.out.println("Client---------------");
			String line=br.readLine();

			while(!line.equals("stop")) {
                            //将用户输入的信息,发送给服务器
			    os.println(line);
                            //刷新输出流,使信息立即到达服务器
			    os.flush();
                            //将客户端传递过来的信息打印出来
			    System.out.println("server:"+is.readLine());
                            //为下次的输入做准备,必须放在这里
			    line=br.readLine();

			}
			os.close();
			is.close();
			socket.close();
		} catch (Exception e) {
			System.out.println("Error:"+e);
		}
	}
}

客户端首先建立socket实例对象,注意socket是双向连接的,所以这里我们用的是tcp连接。

第二个参数是端口号,端口号要注意,不要和现有的端口号冲突。

然后建立socket对象的输入输出流,最后将从服务器传递过来的数据打印,并且将用户输入的信息传递给服务器

server端:

package day01;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Service {
	public static void main(String[] args) {
		try {
			ServerSocket server=null;
			Socket socket=null;
			try {
                            //监听目标端口号
			    server=new ServerSocket(4700);
			} catch (Exception e) {
				System.out.println("Error:"+e);
			}
			System.out.println("server-------------------");
			try {
                            //一旦有请求到来就创建socket对象
			    socket=server.accept();
			} catch (Exception e) {
				System.out.println("Error:"+e);
			}
			String line;
                        //从客户端过来的输入流
			BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        //写到客户端的输出流
			PrintWriter os=new PrintWriter(socket.getOutputStream());
                        //用户的输入
			BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
			System.out.println("Client:"+is.readLine());
			line=br.readLine();
            
			while(!line.equals("stop")) {
                            //将用户的输入传递到客户端
			    os.println(line);
                            //立刻刷新输入流,使信息立即传递到客户端
			    os.flush();
                            //打印客户端传递过来的信息
			    System.out.println("Client:"+is.readLine());
                            //为下次用户的输入做准备,必须放在这里
			    line=br.readLine();
			}
			is.close();
			os.close();
			socket.close();
		} catch (Exception e) {
			System.out.println("Error:"+e);
		}
	}
}

服务器端的实现和客户端差不多,但是如果你细心点,你会发现,服务器端有两行是一样的:

他们的作用都是打印从客户端传输过来的数据。为什么会这样呢?把第一个删了行不行?

答案肯定是不行的。如果把第一行删了,你会发现从客户端传递过来的数据不能及时的打印到服务器端。至于原因,我们又需要谈到执行流程了:

首先,客户端输入一个字符串完毕,该字符串会实时传递到服务器端,服务器端也需要实时的显示出来,然后服务器端输入字符串完毕后,该字符串也会实时的传递到客户端。注意第一遍结束后,后面的操作全部都在while循环中进行。

如果删除,服务器端就需要我们输入数据后才能打印,而且后面每次都是如此,达不到数据实时互通的效果。为什么会这样呢?

首先,在服务器执行到readLine()以后,进程就会阻塞,等待用户的输入,即后面的操作就会停止。等到用户输入了信息,服务器端才会打印出客户端传递过来的数据,并且又会执行readLine(),再次阻塞进程。所以下次客户端输入的信息不能及时显示。等到用户在客户端再次输入信息,才能打印数据。后面一直都会如此。

那么,没有删除又是如何保证实时性的呢?

首先,服务器端会执行打印操作,用户输入数据后,执行到打印操作时,因为readLine()每次执行完毕后会自动跳到下一行,之前已经打印了数据,所以此时的输入流中没有数据,故此处会阻塞。等到客户端输入数据完毕后,输入流里有了值,此处进程被唤醒,打印刚刚客户端输入的数据,并等待用户输入。从而保证了交流的实时性。

因此总结一下:

Client端的实现:

1.创建socket连接,需要ip地址和空闲的端口号

2.创建socket对象的输入流和输出流,用来和服务器端进行交互

3.进行业务,注意及时把数据放进输出流并立马刷新

4.关闭连接

Service端的实现:

1.创建serverSocket对象来监听端口号,一旦有请求到来则创建socket对象

2.创建socket对象的输入输出流

3.执行业务

4.关闭连接

注意:需要先启动客户端然后再启动服务器端

UDP版:

client端:

package day01;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Client {
	public static void main(String[] args) throws IOException {
		// 创建通信类,专门进行端之间的数据通信
		DatagramSocket socket = new DatagramSocket();
		// 用户输入
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String string = br.readLine();
		// 定义服务器端的地址
		InetAddress address = InetAddress.getByName("127.0.0.1");
		// 需要发送的数据
		byte[] data = string.getBytes();
		// 服务器所在的端口号
		int port = 4700;
		// 创建数据报
		DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
		// 发送数据报
		socket.send(packet);

		byte[] data2=new byte[1024];
		//创建数据报,用来接受客户端传递的数据
		DatagramPacket packet2=new DatagramPacket(data2, data2.length);
		//接受数据,在接受之前会阻塞
		socket.receive(packet2);
		//解析数据包,转换为字符串
		String str=new String(data2,0,data2.length);
		System.out.println("客户端问我:"+str);
		socket.close();
	}
}

server端:

package day01;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Service {
	public static void main(String[] args) throws IOException {
		//创建通信类,指定占用的端口号
		DatagramSocket socket=new DatagramSocket(4700);
		byte[] data=new byte[1024];
		//创建数据报,用来接受客户端传递的数据
		DatagramPacket packet=new DatagramPacket(data, data.length);
		//接受数据,在接受之前会阻塞
		socket.receive(packet);
		//解析数据包,转换为字符串
		String str=new String(data,0,data.length);
		System.out.println("客户端问我:"+str);
		
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String string=br.readLine();
		//根据数据包获得客户端地址
		InetAddress address=packet.getAddress();
		//根据数据包获得客户端端口
		int port=packet.getPort();
		//定义要发送的的数据
		byte[] data2=string.getBytes();
		//创建数据包,包含响应的数据
		DatagramPacket packet2=new DatagramPacket(data2, data2.length,address,port);
		//响应客户端
		socket.send(packet2);
		socket.close();
	}
}

总结一下:

客户端发送数据:

1.创建通信类DatagromSocket

2.定义服务器地址,发送的数据,端口号

3.创建并封装数据报DatagromPacket

4.发送该报文

客户端接受数据:

1.创建数组缓存

2.创建接受数据报

3.接受数据

4.解析数据

服务器端接受数据:

同客户端接受数据

服务器端发送数据:

1.创建通信类

2.根据接受报文获取客户端地址,客户端端口号

3.定义发送的数据

4.创建并封装数据报

5.发送该报文

可以看出,udp的实现是利用数据报来实现的。其详细步骤在代码中皆有解释,故不再多言。但是对比和tcp可以明显的发现不同,那就是tcp需要客户端先发起请求,服务器端然后响应。udp是可以服务器主动给客户端发送消息的。当然除此之外还有很多的不同,这里就不再赘述了!

参考博客:点击这里

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值