java学习之路——基于TCP的Socket网络通信实例

第一部分:

 1.什么是socket

   所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
 2.重要的Socket API:

   java.net.Socket继承于java.lang.Object,有八个构造器,其方法并不多,下面介绍使用最频繁的三个方法,其它方法大家可以见JDK-1.3文档。

   . Accept方法用于产生"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例。"阻塞"是一个术语,它使程序运行暂时"停留"在这个地方,直到一个会话产生,然后程序继续;通常"阻塞"是由循环产生的。

   . getInputStream方法获得网络连接输入,同时返回一个IutputStream对象实例,。

   . getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。

   注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。

第二部分:

如何开发一个Server-Client模型的程序

   开发原理:

   服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。

   客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

代码示例:

1:建立主服务器类

package com.lcq.network;

/**
 * 
 * 类名:MainServer
 * 功能:建立主服务器类,接受客户端的信息并显示,与客户端进行交互
 * 时间:
 * 作者:lcq
 * 版本:
 * 
 */

import java.net.ServerSocket;
import java.net.Socket;

public class MainServer {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		
		ServerSocket serverSocket = new ServerSocket(4000);
		//调用socket的accept()方法侦听并接受到此套接字的连接,此方法在连接传入之前一直阻塞。 
		while(true){
			
			Socket socket = serverSocket.accept();
			
			new ServerInputThread(socket).start();
			new SeverOutputThread(socket).start();
			
			
			
		}
		

	}

}


2:建立主服务器的两个线程类(包括向客户端输出和输入的线程)

package com.lcq.network;


/**
 * 
 * 类名:ServerInputThread
 * 功能:建立主服务器的输入线程类,接收客户端的信息后打印出来
 * 时间:
 * 作者:lcq
 * 版本:
 * 
 */

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

public class ServerInputThread extends Thread{

	private Socket socket;
	public ServerInputThread(Socket socket){
		this.socket = socket;
	}
	@Override
	public void run() {
		
		
		while(true){
			try {
				
				//建立输入流
				InputStream is = socket.getInputStream();
				byte[] by = new byte[1024];
				//将输入流里的字节读到字节数组里,并返回读的字节数
				int length = is.read(by);
				//将字节数组里的length个字节转换为字符串
				String str = new String(by,0,length);
				//打印出字符串
				System.out.println(str);
				
				
				
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
	}

	
	
	
	
	
	
	
	
	
	
	
}


 

package com.lcq.network;


/**
 * 
 * 类名:SeverOutputThread
 * 功能:建立主服务器的输出线程类, 向客户端传送信息
 * 时间:
 * 作者:lcq
 * 版本:
 * 
 */


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

public class SeverOutputThread extends Thread{
	
	Socket socket = new Socket();
	public SeverOutputThread(Socket socket){
		this.socket = socket;
	}

	
	@Override
	public void run() {
		
		
		while(true){
			
			try {
				//从socket中得到输出流对象
				OutputStream os = socket.getOutputStream();
				BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
				
				String line = br.readLine();
				os.write(line.getBytes());
				
				
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		
			
		}
		
		
	}
}


3:建立主客户端类

package com.lcq.network;

/**
 * 
 * 类名:MainClient
 * 功能:建立主客户端类,接受服务器端的信息并显示,与服务器端进行交互
 * 时间:
 * 作者:lcq
 * 版本:
 * 
 */


import java.net.Socket;

public class MainClient {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		
		Socket socket = new Socket("127.0.0.1", 4000);
	
			new ClientInputThread(socket).start();
			new ClientOutputThread(socket).start();
	
		

	}

}


4:建立主客户端的两个线程(包括向服务器端输入和输出)

package com.lcq.network;

/**
 * 
 * 类名:ClientInputThread
 * 功能:建立主客户端的输入线程类,接收服务器端的信息后打印出来
 * 时间:
 * 作者:lcq
 * 版本:
 * 
 */

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

public class ClientInputThread extends Thread{
	private Socket socket;
	public ClientInputThread(Socket socket){
		this.socket = socket;
	}
	@Override
	public void run() {
		
		
		while(true){
			try {
				
				//建立输入流
				InputStream is = socket.getInputStream();
				byte[] by = new byte[1024];
				//将输入流里的字节读到字节数组里,并返回读的字节数
				int length = is.read(by);
				//将字节数组里的length个字节转换为字符串
				String str = new String(by,0,length);
				//打印出字符串
				System.out.println(str);
				
				
				
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
}
}


 

package com.lcq.network;

/**
 * 
 * 类名:ClientOutputThread
 * 功能:建立主客户端的输出线程类, 向服务器端传送信息
 * 时间:
 * 作者:lcq
 * 版本:
 * 
 */

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

public class ClientOutputThread extends Thread{

	Socket socket = new Socket();
	public ClientOutputThread(Socket socket){
		this.socket = socket;
	}

	
	@Override
	public void run() {
		
		
		while(true){
			
			try {
				OutputStream os = socket.getOutputStream();
				BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
				
				String line = br.readLine();
				os.write(line.getBytes());
				
				
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		
			
		}
		
		
	}
}


程序运行的效果是:像聊天器一样可以在主客户端和主服务器端相互通信。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值