Java--Socket

Socket

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。

TCP/IP

互联网协议(Internet Protocol Suite)是一个网络通信模型,以及一整个网络传输协议家族,为互联网的基础通信架构。它常被通称为TCP/IP协议族(英语:TCP/IP Protocol Suite,或TCP/IP Protocols),简称TCP/IP。因为该协议家族的两个核心协议:TCP(传输控制协议)和IP(网际协议),为该家族中最早通过的标准。由于在网络通讯协议普遍采用分层的结构,当多个层次的协议共同工作时,类似计算机科学中的堆栈,因此又被称为TCP/IP协议栈(英语:TCP/IP Protocol Stack) 。这些协议最早发源于美国国防部(缩写为DoD)的ARPA网项目,因此也被称作DoD模型(DoD Model)。这个协议族由互联网工程任务组负责维护。
TCP/IP提供点对点的链接机制,将数据应该如何封装、定址、传输、路由以及在目的地如何接收,都加以标准化。它将软件通信过程抽象化为四个抽象层,采取协议堆栈的方式,分别实现出不同通信协议。协议族下的各种协议,依其功能不同,被分别归属到这四个层次结构之中,常被视为是简化的七层OSI模型。

TCP

TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于端到端的通讯。
TCP提供的是一种可靠的数据流服务,采用“带重传的肯定确认”技术来实现传输的可靠性。TCP还采用一种称为“滑动窗口”的方式进行流量控制,所谓窗口实际表示接收能力,用以限制发送方的发送速度。
如果IP数据包中有已经封好的TCP数据包,那么IP将把它们向‘上’传送到TCP层。TCP将包排序并进行错误检查,同时实现虚电路间的连接。TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重传。
TCP将它的信息送到更高层的应用程序,例如Telnet的服务程序和客户程序。应用程序轮流将信息送回TCP层,TCP层便将它们向下传送到IP层,设备驱动程序和物理介质,最后到接收方。
面向连接的服务(例如Telnet、FTP、rlogin、X Windows和SMTP)需要高度的可靠性,所以它们使用了TCP。DNS在某些情况下使用TCP(发送和接收域名数据库),但使用UDP传送有关单个主机的信息。

UDP

UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。
UDP通讯时不需要接收方确认,属于不可靠的传输,可能会出现丢包现象,实际应用中要求程序员编程验证。
UDP与TCP位于同一层,但它不管数据包的顺序、错误或重发。因此,UDP不被应用于那些使用虚电路的面向连接的服务,UDP主要用于那些面向查询—应答的服务,例如NFS。相对于FTP或Telnet,这些服务需要交换的信息量较小。使用UDP的服务包括NTP(网络时间协议)和DNS(DNS也使用TCP)。
欺骗UDP包比欺骗TCP包更容易,因为UDP没有建立初始化连接(也可以称为握手)(因为在两个系统间没有虚电路),也就是说,与UDP相关的服务面临着更大的危险。

基于TCP的socket

//Server

@Slf4j
public class Server {
	private static ServerSocket server = null;

	static void init() throws IOException {
		synchronized (Server.class) {
			if (server == null) {
				server = new ServerSocket(ServerParams.PORT);
			}
			log.info("服务端已启动~.....");
			while (true) {
				Socket client = server.accept();
				new ReadAndWrite(client).start();
			}
		}
	}

	public static void main(String[] args) throws IOException {
		Server.init();
	}

}

@Slf4j
@AllArgsConstructor
class ReadAndWrite extends Thread {

	private Socket socket;

	@Override
	public void run() {
		log.info("有客户端接入:{}", socket.getInetAddress());
		try {
			BufferedReader reder = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			PrintWriter writer = new PrintWriter(socket.getOutputStream());
			String readMsg = "";
			String respMsg = "";
			while (true) {
				readMsg = reder.readLine();
				log.info("客户端--{}---说:{}", socket.getInetAddress(), readMsg);
				respMsg = readMsg + "---服务端收到!";

				writer.println(respMsg);
				writer.flush();
			}
		} catch (Exception e) {
			log.error("客户端连接异常...", e);
		}

	}
}

//Client

@Slf4j
public class Client {

	private static Socket client = null;

	static void init() throws UnknownHostException, IOException {
		synchronized (Client.class) {
			if (client == null) {
				client = new Socket(ServerParams.HOST, ServerParams.PORT);
			}
			log.info("客户端已启动...");

			// 获取输出流---向服务端发送信息
			PrintWriter writer = new PrintWriter(client.getOutputStream());
			// 获取输入流---接受服务端信息
			BufferedReader reder = new BufferedReader(new InputStreamReader(client.getInputStream()));

			String writerMsg = "";
			String respMsg = "";
			while (true) {
				writerMsg = new Scanner(System.in).nextLine();
				writer.println(writerMsg);
				writer.flush();

				respMsg = reder.readLine();
				log.info("服务端回复:{}", respMsg);
			}
		}
	}

	public static void main(String[] args) throws UnknownHostException, IOException {
		Client.init();
	}
}

server----------------------------------------------------------------------
2019-03-11 18:01:59,323 [main] INFO  com.haha.socket.tcp.server.Server - 服务端已启动~.....
2019-03-11 18:02:02,834 [Thread-1] INFO  com.haha.socket.tcp.server.ReadAndWrite - 有客户端接入:/127.0.0.1
2019-03-11 18:02:05,892 [Thread-2] INFO  com.haha.socket.tcp.server.ReadAndWrite - 有客户端接入:/127.0.0.1
2019-03-11 18:02:10,194 [Thread-1] INFO  com.haha.socket.tcp.server.ReadAndWrite - 客户端--/127.0.0.1---说:111
2019-03-11 18:02:13,510 [Thread-2] INFO  com.haha.socket.tcp.server.ReadAndWrite - 客户端--/127.0.0.1---说:222
server----------------------------------------------------------------------


client1---------------------------------------------------------------------------------
2019-03-11 18:02:02,832 [main] INFO  com.haha.socket.tcp.client.Client - 客户端已启动...
111
2019-03-11 18:02:10,195 [main] INFO  com.haha.socket.tcp.client.Client - 服务端回复:111---服务端收到!
client1---------------------------------------------------------------------------------

client2---------------------------------------------------------------------------------
2019-03-11 18:02:05,893 [main] INFO  com.haha.socket.tcp.client.Client - 客户端已启动...
222
2019-03-11 18:02:13,511 [main] INFO  com.haha.socket.tcp.client.Client - 服务端回复:222---服务端收到!
client2---------------------------------------------------------------------------------

基于UDP的socket

//server
/**
 * UDP
 */
@Slf4j
public class Server {
	private static DatagramSocket server = null;

	static void init() throws Exception {
		synchronized (Server.class) {
			if (server == null) {
				server = new DatagramSocket(ServerParams.PORT);
			}
			log.info("UDP 服务端已启动...");
			// 定义数据包,用于存储数据
			byte[] buf = new byte[1024];
			DatagramPacket dp = new DatagramPacket(buf, buf.length);
			while (true) {
				server.receive(dp);
				if (dp.getAddress() != null) {
					String ip = dp.getAddress().getHostAddress();
					String data = new String(dp.getData(), 0, dp.getLength());
					log.info("收到信息:ip---{},data---{}", ip, data);
				}
			}
		}
	}

	public static void main(String[] args) throws Exception {
		Server.init();
	}
}

//client

public class Client {
	public static void main(String[] args) throws Exception {
		DatagramSocket ds = new DatagramSocket();// 通过DatagramSocket对象创建udp服务
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));// 从键盘上面输入文本
		String line = null;
		while ((line = bufr.readLine()) != null)// 当输入不为空时
		{
			if ("byebye".equals(line))// 当输入为byebye时退出程序
				break;
			// 确定好数据后,并把数据封装成数据包
			byte[] buf = line.getBytes();
			DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName(ServerParams.HOST),
					ServerParams.PORT);// 发送至指定IP,指定端口
			ds.send(dp);// 通过send方法将数据包发送出去
		}
		ds.close();// 关闭资源
	}
}
server---------------------------------------------------------
2019-03-11 18:23:08,129 [main] INFO  com.haha.socket.udp.server.Server - UDP 服务端已启动...
2019-03-11 18:23:12,864 [main] INFO  com.haha.socket.udp.server.Server - 收到信息:ip---127.0.0.1,data---21213
2019-03-11 18:23:31,294 [main] INFO  com.haha.socket.udp.server.Server - 收到信息:ip---127.0.0.1,data---21515615
2019-03-11 18:24:37,817 [main] INFO  com.haha.socket.udp.server.Server - 收到信息:ip---127.0.0.1,data---5555
2019-03-11 18:24:41,690 [main] INFO  com.haha.socket.udp.server.Server - 收到信息:ip---127.0.0.1,data---666
server---------------------------------------------------------

client1---------------------------------------------------------
123
21213
21515615
client1---------------------------------------------------------

client2---------------------------------------------------------
5555
666
client2---------------------------------------------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值