java初级-多线程下的TCP编程

本程序为在多线程条件下完成客户端与服务器进行的文字交互, 如果使用的是单线程, 那么当客户端发送第一条信息后, 在服务器端没有响应的情况下, socket套接字还在服务器那里, 则客户端无法继续发送信息, 对于服务器端亦然. 所以需要多线程操作.

1. 定义一个接收信息的线程

package com.gdzy.TCPmultipleThread;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;

public class ReceiveInfo implements Runnable {

	private Socket soc1;  //定义一个Socket类型的引用, 使其与调用这个线程的类建立起联系
	//无参构造
	public ReceiveInfo(){
		
	}
	//有参构造, 调用这个线程时将socket对象传入
	public ReceiveInfo(Socket soc1){
		this.soc1 = soc1;
	}
	//重写run方法
	public void run(){
		
		try {
			//得到soc1 套接字引用的 输入流
			InputStream is1 = soc1.getInputStream();
			//将套接字的输入流, 封装到缓存流进行处理
			BufferedReader br1 = new BufferedReader(new InputStreamReader(is1));
			//循环读取缓存流中的数据并打印到控制台
			while(true){	
				String info = br1.readLine();
				System.out.println(info);
				if(info.endsWith("bye") || info.endsWith("再见")|| info.endsWith("88")|| info.endsWith("拜拜")){
					break;
					
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
}

2. 创建一个发送信息的线程

package com.gdzy.TCPmultipleThread;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class SendInfo implements Runnable {	
	private Socket socSend; //定义一个Socket类型的引用, 使其与调用这个线程的类建立起联系
	private String name;   // 定义一个字符串变量,使其在发送信息时携带此名字, 在类调用这个线程时传入这个参数
	//无参构造
	public SendInfo(){
		
	}
	//有参构造, 调用这个线程时将socket对象传入
	public SendInfo(Socket socSend, String name){
		this.socSend = socSend;
		this.name = name;
	}
	
	//重写run方法
	public void run() {			
		
		try {
			Scanner input = new Scanner(System.in);	 //创建一个键盘输入流		
			OutputStream os1  = socSend.getOutputStream();	 // 得到套接字socket 引用socSend的输出流	
			//打印流, 此打印流的输出方向为 套接字socSend的输出流,即 将后面打印流中的信息 封装到, socSend的输出流中
			PrintWriter pw1 = new PrintWriter(os1,true);  // boolean 变量;如果为 true,则 printlnprintfformat 方法将刷新输出缓冲区
			
			//循环键盘输入, 并将输入信息封装到套接字的输出流中发送
			while(true){
				String info = input.next();
				pw1.println(name+":"+info); //此处不可以用print, 因为print 不具有刷新的功用,  println具有自动刷新的功能
			//当info中含有如下字符时, 跳出循环
				if(info.endsWith("bye") || info.endsWith("再见")|| info.endsWith("88")|| info.endsWith("拜拜")){
					break;
					
				}
				
			}
				
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

	
}
3. 服务器端

package com.gdzy.TCPmultipleThread;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server1 {

	/**
	 * 多线程下的 服务器端
	 */
	public static void main(String[] args) throws Exception {

		ServerSocket ss1 = new ServerSocket(1237); //创建绑定到特定端口的服务器套接字。		
		Socket socServer = ss1.accept();  //侦听并接受到此套接字的连接。
		
		Thread t1 = new Thread(new ReceiveInfo(socServer));   //创建接收消息线程
 		Thread t2 = new Thread(new SendInfo(socServer,"服务器")); //创建发送消息线程
 		
 		t1.start();   //接收线程准备就绪
 		t2.start();   //发送线程准备就绪
	 

	}

}

4. 客户端

package com.gdzy.TCPmultipleThread;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client1 {

	/**
	 * 多线程中的  客户端1	 * 
	 */
	public static void main(String[] args) throws Exception {
		//创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
		Socket socClient = new Socket(InetAddress.getLocalHost(),1237); 
		//创建接收线程
		Thread t1 = new Thread(new ReceiveInfo(socClient));
		//创建发送线程
		Thread t2 = new Thread(new SendInfo(socClient,"客户端"));
		//使线程处于就绪状态
		t1.start();
		t2.start();
	
	}

}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值