基于TCP协议的网络编程学习笔记(1)
来源:互联网 发布:网易邮箱端口号 编辑:程序博客网 时间:2024/06/05 15:28
TCP/IP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket ,从而在通信的两端之间形成网络虚拟链路。一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。 JAVA对基于TCP/IP协议的网络通信提供了良好的封装。java使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信.
(一)阻塞式的Scoket通信
(1)使用ServletSocket创建TCP服务器
TCP通信的两个实体之间并没有服务器,客户端之分,但那是两个通信实体已经建立虚拟链路之后。。在两个通信实体没有建立虚拟链路之前,必须有一个通信实体先做出“主动姿态”,主动接收来自其它通信实体的连接请求.
Java中能接收其它通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。
Socket accept():如果接收到一个客户端的 Socket连接请求,该方法将返回一个与客户端Socket对应的Socket,否则该方法一直处于等待状态,线程也被阻塞。
为了创建ServerSocket对象,ServerSocket类提供了如下几个构造器
ServerSocket(int port)
ServerSocket(int port,int backlog)
ServerSocket(int port,int backlog,InetAddress localAddr)
当ServerSocket使用完毕,应使用ServerSocket的close()方法来关闭该ServerSocket。通常情况下,服务器不应该只接爱一个客户端请求,而应该不断地接受来自客户端的所有请求,所以java程序通常会通过循环,不断地调用ServerSocket的accept()方法。
如下代码断
//创建一个ServerSocket,用于监听客户端Socket的连接请求 ServerSocket ss = new ServerSocket(30000); //采用循环不断接受来自客户端的请求 while (true) { //每当接受到客户端Socket的请求,服务器端也对应产生一个Socket Socket s = ss.accept(); //将Socket对应的输出流包装成PrintStream PrintStream ps = new PrintStream(s.getOutputStream()); //进行普通IO操作 ps.println("欢迎您跟随阿堂(网络时空)一起来学习Scoket的相关知识"); //关闭输出流,关闭Socket ps.close(); s.close(); }
(2)使用Socket进行通信
客户端通常使用Socket的构造器来连接到指定服务器,Socket通常可使用如下两个构造器
Socket(InetAddress/String remoteAddress,int port)Socket(InetAddress/String remoteAddress,int port,InetAddress localAddr,int localPort)
如
Socket socket = new Socket("127.0.0.1" , 30000);
// 下面就可以使用Socket进行通信了
……
当程序执行上面代码时,该代码将连接到指定ip地址和端口的服务器,让服务器的ServerSocket的accept()方法向下执行,于是服务器和客户端就产生一对互相连接的Socket了
当客户端,服务器产生了对应的Socket之后,这时候程序就无须区分服务器,客户端了,而是通过各自的Socket进行通信,Socket提供了如下两个方法来获取输入流和输出流
InputStream getInputStream():返回该Socket对象对应的输入流,让程序通过该输入流从Socket中取出数据.
OutputStream getOutputStream():返回该Socket对象对应的输出流,让程序通过该输出流向Socket中输出数据.
如:
import java.net.*;import java.io.*;public class Server{ public static void main(String[] args) throws IOException { //创建一个ServerSocket,用于监听客户端Socket的连接请求 ServerSocket ss = new ServerSocket(30000); //采用循环不断接受来自客户端的请求 while (true) { //每当接受到客户端Socket的请求,服务器端也对应产生一个Socket Socket s = ss.accept(); //将Socket对应的输出流包装成PrintStream PrintStream ps = new PrintStream(s.getOutputStream()); //进行普通IO操作 ps.println("服务器向你发送信息啦!"); //关闭输出流,关闭Socket ps.close(); s.close(); } }}
(3)加入多线程
当我们使用传统的BufferReader的readLine()方法读取数据时,当该方法成功返回之前,线程被阻塞,程序无法继续执行。考虑到这个原因,因此服务器应该为每个Socket单独启动一条线程,每条线程与一个客户端进行通信.
同样,客户端读取服务器数据时,线程也会被阻塞,所以系统也应该为客户端单独启动一条线程,该客户端线程专门负责读取服务器数据.
下面的实现一个命令行的C/S聊天室应用,服务器应该包含多条线程,每个Socket对应一条线程,该线程负责读取Socket对应输入流的数据(从客户端发送过来的数据),并将读到的数据向每个 Socket输出流发送一遍(将每一个客户端的数据”广播”给其它客户端),因此需要在服务器端使用List来保存所有的Socket。
服务器端提供了两个类:一个是创建 ServerSocket监听的主类,一个是负责处理每个Scoket通信的线程类
如下所示
import java.net.*;import java.io.*;import java.util.*;public class MyServer{ //定义保存所有Socket的ArrayList public static ArrayList<Socket> socketList = new ArrayList<Socket>(); public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(30000); while(true) { //此行代码会阻塞,将一直等待别人的连接 Socket s = ss.accept(); socketList.add(s); //每当客户端连接后启动一条ServerThread线程为该客户端服务 new Thread(new ServerThread(s)).start(); } }}
import java.io.*;import java.net.*;import java.util.*;//负责处理每个线程通信的线程类public class ServerThread implements Runnable{ //定义当前线程所处理的Socket Socket so = null; //该线程所处理的Socket所对应的输入流 BufferedReader br = null; public ServerThread(Socket s) throws IOException { this.so = s; //初始化该Socket对应的输入流 br = new BufferedReader(new InputStreamReader(so.getInputStream())); } public void run() { System.out.println("----Client :" + s.getPort() + " connected-----"); while (true) { String line = null; while ((line = readFromClient()) != null) { for (Socket socket : MyTCPServer.socketList) { if (socket == s) { continue; } try { System.out.println("send to socket :" + s.getPort()); PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println(line); } catch (IOException e) { e.printStackTrace(); } } } } } //定义读取客户端数据的方法 private String readFromClient() { try { return br.readLine(); } //如果捕捉到异常,表明该Socket对应的客户端已经关闭 catch (IOException e) { //删除该Socket。 MyServer.socketList.remove(s); } return null; }}
客户端也同样提供了两个类:一个是负责读取键盘输入的Myclient,并将用户输入的数据写入Socket对应的输出流中,也就是客户端程序的主线程类,一个是负责读取Socket对应输入流中的数据(从服务器发送过来的数据).
import java.net.*;import java.io.*;public class MyClient{ public static void main(String[] args) throws IOException { Socket s = s = new Socket("127.0.0.1" , 30000); //客户端启动ClientThread线程不断读取来自服务器的数据 new Thread(new ClientThread(s)).start(); //获取该Socket对应的输出流 PrintStream ps = new PrintStream(s.getOutputStream()); System.out.println("input:"); Scanner scanner = new Scanner(System.in); while (true) {// System.out.println(scanner.next()); ps.println(s.getLocalPort()+":"+scanner.next()); } }}
import java.io.*;import java.net.*;import java.util.*;public class ClientThread implements Runnable{ //该线程负责处理的Socket private Socket s; //该现成所处理的Socket所对应的输入流 BufferedReader br = null; public ClientThread(Socket s) throws IOException { this.s = s; br = new BufferedReader( new InputStreamReader(s.getInputStream())); } public void run() { System.out.println("----Client : " + s.getLocalPort() + " start-----"); try { while (true) { String line = null; while ((line = br.readLine()) != null) { String[] split = line.split(":"); String src = split[0]; String content = split[1]; System.out.println("receive from " + src + ":" + content); } } } catch (IOException e) { e.printStackTrace(); } }}
- 基于TCP协议的网络编程学习笔记(1)
- 基于TCP协议的网络编程--socket编程(1)
- 基于TCP协议的网络编程
- 基于Tcp协议的网络编程
- 基于TCP协议的网络编程
- 基于TCP/IP协议的网络编程
- 17.3 基于TCP协议的网络编程
- 基于TCP协议的网络编程:
- 网络编程之基于TCP协议的网络编程
- 【JavaSE学习笔记】网络编程_UDP协议,TCP协议
- 基于TCP协议的网络编程--socket编程(2)
- Socket编程基础--基于TCP协议的网络编程
- 基于TCP/IP协议的网络编程—Socket编程
- java Socket编程学习笔记 01——基于TCP协议的Socket编程
- TCP/IP网络编程 学习笔记_5 --基于TCP的服务端/客服端
- 基于UDP、TCP协议的C#网络编程之一
- 【转载】 基于UDP、TCP协议的C#网络编程
- socket编程-- 基于TCP协议的网络程序
- lua捕获异常(tryCatch封装)
- 手指上几乎全没有月芽儿
- iOS AutoLayout与AutoSizing
- MySQL 5.0 Load data infile 与 Insert 性能差异比较
- Mongodb安装 for windows7 64位
- 基于TCP协议的网络编程学习笔记(1)
- 使用mysql 统计函数 结果为null时返回值改为0
- Eclipse调试:F5、F6、F7、F8
- 个人开源项目(学习与研究)
- Oracle 解决'PLAN_TABLE' is old version问题
- java中 stack与和heap的区别
- Android中Canvas绘图基础详解(附源码下载)
- 线程同步 总结 内核对象
- Android 增强版百分比布局库