Socket套接字/TCP


关于网络编程,就不得不提Socket套接字,下面就来讲讲对Socket的一些理解以及运用!


套接字(Socket),指的是一个程序的IP和端口号的结合。


我们可以这样理解:所谓网络通信,实际上指的是两台主机上面的两个程序之间的通信,

两个程序在进行通信(数据交换)的时候需要建立起一个“连接”,我们就可以认为这个连接就是一个网络套接字.



假设A主机的程序1要和B主机的程序2进行数据交换,

首先A主机的程序1需要通过B主机的IP找到B主机,然后再通过程序的端口号找到B主机的程序2

找到之后A主机的程序1B主机的程序2之间就建立起了一个连接(Socket),通过这个连接就可以实现两者之间的数据交换。



当A的程序1和B的程序2建立起连接(Socket)之后,不是直接通过socket进行数据交换的,

而是通过Socket里面的流进行通信的。

在Socket有两根流,一根是从A到B,另一根是从B到A的,对于同一根流,如果对于A是输出,那么对于B就是输入。

如下图:




熟悉了socket的概念之后,下面通过一个简单的实例来模拟一下socket的使用!

程序场景:A主机的程序1连接B主机程序2进行网络通信。此处B主机作为服务器![java.net.Socket]包


B主机程序2

package com.socket;

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

/**
 * 这个类对应的是B主机的程序2
 * @author admin
 *
 */
public class MyServer {

	public static void main(String[] args) {
		
		try {
			// 创建网络服务器,指定端口,提供给客户端连接
			ServerSocket server = new ServerSocket(9555);
			
			// 让服务器等待网络连接,服务器在等待网络连接的时候,处于一个等待状态
			// 不会往下执行,直到有客户端发送请求,服务器在接受到了请求之后才会继续往下执行
			Socket socket = server.accept();
			
			// 此处直到有客户端发送请求时,才会执行
			System.out.println("此处直到有客户端发送请求时,才会执行!!!");
			
			// 通过socket获取到它的输入流
			InputStream is = socket.getInputStream();
			
			InputStreamReader isr = new InputStreamReader(is);
			
			BufferedReader br = new BufferedReader(isr);
			
			// 打印客户端输入的内容
			String str=null;
			while((str=br.readLine())!=null) {
				System.out.println(str);
			}
			
			br.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}


注意:

accept() : 让服务器等待网络连接,服务器在等待网络连接的时候,处于一个等待状态,不会往下执行,直到有客户端发送请求,服务器在接受到了请求之后才会继续往下执行!!所以上面accept方法行下面的的代码在启动服务器[MyServer]时不会立即执行!!



A主机的程序1

package com.socket;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 这个类对应的是A主机的程序1
 * @author admin
 *
 */
public class MyClient {

	public static void main(String[] args) {
		try {
			// 通过服务器的IP和端口号创建socket请求,一旦请求成功就创建socket
			Socket socket = new Socket("localhost", 9555);
			
			// 因为是客户端向服务器发送消息,所以获取输出流
			OutputStream os = socket.getOutputStream();
			
			PrintWriter pw = new PrintWriter(os);
			
			pw.println("A主机的程序1连接B主机程序2进行网络通信----演示");
			// 此处记得flush()
			pw.flush();
			// 关闭流,养成习惯
			pw.close();
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}


上面程序当然得先启动服务器[MyServer],然后客户端[MyClient]才能通过socket正常连接!!

此处特别注意,先启动服务器客户端才能连接,否则先启动客户端的话会报错!!!为什么会这样呢,这就是典型的

TCP模式,客户端必须确定可以建立连接,需要服务器端返回可以连接(三次握手)的信号!!!!



上面的实例只是单方面的客户端向服务器发送消息,但是很多情况下是需要客户端和服务器互相发送消息的,有点像QQ的意思!!如下图:



以下为通过线程发送和接收信息,Socket持续通信的实例代码:

服务器:

package com.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * 服务器
 * @author admin
 *
 */
public class TestServer {

	public static void main(String[] args) {
		try {
			// 创建服务器端口,给客户端提供连接
			ServerSocket server = new ServerSocket(9555);
			// 等待客户端连接
			Socket socket = server.accept();
			
			// 从socket获取到输出流
			OutputStream os = socket.getOutputStream();
			PrintWriter pw = new PrintWriter(os);
			
			// 从socket获取到输入流
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			
			ReceiveMsg rm = new ReceiveMsg(br);
			SendMsg sm = new SendMsg(pw);
			
			// 启动线程
			sm.start();
			rm.start();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

客户端:

package com.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 客户端
 * @author admin
 *
 */
public class TestClient {
	
	public static void main(String[] args) {
		try {
			// 连接服务器
			Socket socket = new Socket("localhost",9555);
			
			// 从socket获取到输入流
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			
			// 从socket获取到输出流
			OutputStream os = socket.getOutputStream();
			PrintWriter pw = new PrintWriter(os);
			
			// 启动接收和发送两个线程
			ReceiveMsg rm = new ReceiveMsg(br);
			SendMsg sm = new SendMsg(pw);
			
			sm.start();
			rm.start();
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

发送信息线程:

package com.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

/**
 * 此线程用于发送信息
 * @author Admin
 *
 */
public class SendMsg  extends Thread{
	
   // 输出流
   private 	PrintWriter pw;
	
   public SendMsg(PrintWriter pw){
	   this.pw = pw;
   }
   
    // 此线程用于发送信息
    public void run(){
    	// 输入流,从控制台读取信息
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String str=null;
		try {
			// 输出信息
			while((str=br.readLine())!=null){
		             pw.println(str);
		             pw.flush();
			}
			// 关闭流
			pw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
}

接收信息线程:

package com.test;
import java.io.BufferedReader;
import java.io.IOException;
/**
 * 此线程用于接收信息
 * @author Admin
 *
 */
public class ReceiveMsg extends Thread {
	// 输入流
	private BufferedReader br;
	
	public ReceiveMsg(BufferedReader br){
		this.br=br;
	}

	// 此线程用于接收信息
	public void run(){
		String str=null;
		try {
			// 读取信息
			while((str=br.readLine())!=null){
				System.out.println(str);				
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}	
}




文中有考虑不周到的地方,欢迎大家指正,共同进步!!!!!



以上           

                            










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值