您的位置:首页 > 理论基础 > 计算机网络

Socket套接字/TCP

2015-11-22 22:10 661 查看
关于网络编程,就不得不提Socket套接字,下面就来讲讲对Socket的一些理解以及运用!

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

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

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



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

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

找到之后A主机的程序1和B主机的程序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();
}
}
}


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

以上           

                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络编程 socket