2021-10-29

前言的

传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793 [1] 定义。
TCP旨在适应支持多网络应用的分层协议层次结构。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。TCP假设它可以从较低级别的协议获得简单的,可能不可靠的数据报服务。 原则上,TCP应该能够在从硬线连接到分组交换或电路交换网络的各种通信系统之上操作。

应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。

一、客户端

package cli_TCP;

import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class cli_TCP{
	//创建输入函数对象
	Scanner input = new Scanner(System.in);
	JTextArea area;
	JTextField field;
	BufferedReader reader;
	PrintWriter writer;
	Socket sock;
	String network;
	int port;
	
	//构造函数
	//设置网络IP地址与端口
	//UnknownHostException, IOException抛出Socket错误声明
	cli_TCP() throws UnknownHostException, IOException{
			System.out.println("请输入服务器IP:");
			network = input.next();
			System.out.println("network:"+network);
			System.out.println("请输入服务器端口号:");
			port = input.nextInt();
			System.out.println("port:"+port);
			//创建套接子
			sock = new Socket(network,port);
			
			//设置窗口
			setframe();
			
			InputStreamReader streamReader = new InputStreamReader(sock.getInputStream());
			//创建读取信息对象
			reader = new BufferedReader(streamReader);
			//创建发送信息对象
			writer = new PrintWriter(sock.getOutputStream());
			System.out.println("networking is link");
	}
	//主函数,UnknownHostException, IOException抛出Socket错误声明
	public static void main(String[] args) throws UnknownHostException, IOException{
		cli_TCP liyangwei = new cli_TCP();
		liyangwei.go();
	}
	public void go(){
		//创建一个线程来接收数据
		Thread readerThread = new Thread(new receive());
		readerThread.start();
	}
	//设置窗口
	void setframe() {
		JFrame frame = new JFrame();
		//设置窗口关闭时程序结束
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//创建控制面板
		JPanel panel1 = new JPanel();
		JPanel panel2 = new JPanel();
		//创建两行一列的网格控制面板
		JPanel panel3 = new JPanel(new GridLayout(2,1));
		JPanel panel4 = new JPanel();
		JPanel panel5 = new JPanel();
		//使用默认布局设置面板
		panel1.setLayout(new BorderLayout());
		area = new JTextArea();//15,50
		area.setLineWrap(true);
		area.setWrapStyleWord(true);
		area.setEditable(true);
		JScrollPane scrollpane = new JScrollPane(area);
		scrollpane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrollpane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		field = new JTextField(20);
		//发送文本框添加键盘监听事件
		field.addKeyListener(new myKeyListener());
		JButton sendButton = new JButton("send");
		JButton button1 = new JButton("未知1");
		JButton button2 = new JButton("未知2");
		JButton button3 = new JButton("未知3");
		JButton button4 = new JButton("未知4");
		//按钮添加监听事件
		sendButton.addActionListener(new SendButtonListener());
		//控制面板添加组件
		panel1.add(scrollpane,BorderLayout.CENTER);
		panel2.add(field);
		panel2.add(sendButton);
		panel3.add(button1);
		panel3.add(button2);
		panel5.add(button3);
		panel5.add(button4);
		//窗口添加控制面板
		frame.getContentPane().add(panel1,BorderLayout.CENTER);
		frame.getContentPane().add(panel2,BorderLayout.SOUTH);
		frame.getContentPane().add(panel3,BorderLayout.WEST);
		frame.getContentPane().add(panel4,BorderLayout.EAST);
		frame.getContentPane().add(panel5,BorderLayout.NORTH);
		//frame.add(panel,BorderLayout.CENTER);
		//设置窗口的大小
		frame.setSize(400,500);
		//设置窗口为可见的
		frame.setVisible(true);
	}
	//按钮发送信息监听
	public class SendButtonListener implements ActionListener{
		public void actionPerformed(ActionEvent ev){
			try{
				//发送框获取文本并发送
				writer.println(field.getText());
				writer.flush();
			}catch(Exception ex){
				ex.printStackTrace();
			}
			//发送框设置文本为空
			field.setText("");
			//发送框获取焦点
			field.requestFocus();
		}
	}
	//键盘Enter发送信息
		class myKeyListener extends JPanel implements KeyListener{
			/**
			 * 用来表示类的不同版本之间的兼容性
			 */
			private static final long serialVersionUID = 1L;
			
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == KeyEvent.VK_ENTER) {
					try{
						//获取发送框信息并发送
						writer.println(field.getText());
						writer.flush();
					}catch(Exception ex){
						ex.printStackTrace();
					}
					//发送框设置文本为空
					field.setText("");
					//发送框获取焦点
					field.requestFocus();
				}
			}
			public void keyReleased(KeyEvent e) {
				
			}
			public void keyTyped(KeyEvent e) {
				
			}
		}
	//接收信息线程
	public class receive implements Runnable{
		public void run(){
			String message;
			try{
				//读取接收到的信息
				while((message = reader.readLine())!=null){
					System.out.println("read"+message);
					//接收到的信息添加到文本域框
					area.append(message+"\n");
				}
			}catch(Exception ex){
				ex.printStackTrace();
			}
		}
	}
}

二、服务器

package ser_TCP;

import java.io.*;
import java.net.*;
import java.util.*;


public class ser_TCP{
	//创建输入数据对象
	Scanner input = new Scanner(System.in);
	int port;
	String message;
	ServerSocket serverSock;
	//套接子
	Socket socket;
	BufferedReader reader;
	PrintWriter writer;
	ArrayList<PrintWriter> clientOutputStreams;
	
	//构造函数
	//throws IOException抛出serverSock错误
	ser_TCP() throws IOException{
		//设置服务器端口号
		System.out.println("请输入端口号:");
		port = input.nextInt();
		System.out.println("port:"+port);
		//创建服务套接子
		serverSock = new ServerSocket(port);
		
		//创建客户端容器
		clientOutputStreams = new ArrayList<PrintWriter>();
	}
	
	//主函数
	public static void main(String[] args) throws IOException{
		new ser_TCP().go();
	}
	//主函数开始
	public void go(){
		//创建接收数据线程
		Thread readerThread = new Thread(new receive());
		readerThread.start();
	}
	//接收数据线程
	public class receive implements Runnable{
		public void run() {
			while(true) {
				try {
					//服务器套接子转换为套接子
					socket = serverSock.accept();
					
					InputStreamReader isReader = new InputStreamReader(socket.getInputStream());
					//创建读取信息对象
					reader = new BufferedReader(isReader);
					//创建发送消息对象
					writer = new PrintWriter(socket.getOutputStream());
					
					//客户端容器中添加客户端
					clientOutputStreams.add(writer);
					System.out.println("got a connection");
					System.out.println("serverSocket:"+serverSock);
					System.out.println("socket:"+socket);
					
					/*创建发送数据线程
					Thread writeThread = new Thread(new send());
					writeThread.start();
					*/
					
					//读取客户端数据
					while ((message = reader.readLine()) != null){
						//打印从客户端接收到的数据
						System.out.println("read:"+message);
						//发送消息给客户端函数
						tellEveryone();
					}
				} catch (IOException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
			}
		}
	}
	/*发送数据线程
	public class send implements Runnable{
		public void run() {
		
		}
	}
	*/
	
	//发送消息给每一个客户端
	public void tellEveryone(){
		Iterator it = clientOutputStreams.iterator();
		//遍历it迭代器
		while(it.hasNext()){
			try{
				PrintWriter writer = (PrintWriter) it.next();
				//发送消息给客户端
				writer.println(message);
				//刷新
				writer.flush();
			}catch(Exception ex){
				ex.printStackTrace();
			}
		}
	}
}

参考文献

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值