JAVA网络编程之——TCP通信
来源:互联网 发布:手机拍照扫描软件 编辑:程序博客网 时间:2024/06/10 15:04
JAVA网络编程之——TCP通信
TCP是面向连接的,所以是C/S架构,服务器端ServerSocket首先要创建启动,然后监听某一个端口,等待Client的Socket连接,如果有连接发过来,就创建一个专门的Socket_New连接用于和这个Client的Socket进行通信。
那么问题来了:
1. Client的Socket连接有自已的IP和Port,那服务器与它通信的这个Socket_New的端口号是不是ServerSocket监听的端口号呢?建立连接——>数据通信,这个具体流程怎样?
2. 服务器端 多线程解决多Client的方法。
首先,看一下Client和Server的交互过程:
Socket一些常用方法 :
getInetAddress(); 远程服务端的IP地址
getPort(); 远程服务端的端口
getLocalAddress() 本地客户端的IP地址
getLocalPort() 本地客户端的端口
getInputStream(); 获得输入流
getOutStream(); 获得输出流
值得注意的是,在这些方法里面,最重要的就是getInputStream()和getOutputStream()了。一般不直接使用,因为网络上的流是字节流,JAVA中一般转成字符流,再包装一下进行更方便的处理。
getInetAddress(); 远程服务端的IP地址
getPort(); 远程服务端的端口
getLocalAddress() 本地客户端的IP地址
getLocalPort() 本地客户端的端口
getInputStream(); 获得输入流
getOutStream(); 获得输出流
值得注意的是,在这些方法里面,最重要的就是getInputStream()和getOutputStream()了。一般不直接使用,因为网络上的流是字节流,JAVA中一般转成字符流,再包装一下进行更方便的处理。
下面看一下最基本的TCP Server的编写步骤,客户端可以用Windows自带的telnet来测试。
//1.创建服务器端SocketServerSocket ss = new ServerSocket(10001);System.out.println("等待客户端连接.....");//2.阻塞等待客户端连接Socket s = ss.accept();System.out.println("连接成功!");//3.程序运行到此处表明连接成功,获取Socket的输入输出流OutputStream ops = s.getOutputStream();InputStream ins = s.getInputStream();//4.服务器返回给客户端一个信息ops.write("Hello,欢迎访问TCP服务器".getBytes());//5.把网络字节流转换为字符流再包装成Buffer流BufferedReader br = new BufferedReader(new InputStreamReader(ins));//6.利用BufferReader的"行读"功能,读取客户端输入的一行数据// 此处会阻塞读入,直到客户端输入一行数据(telnet输入完成回册)System.out.println(br.readLine());//7.关闭包装类会自动关闭包装类中所有的底层类br.close();s.close();ss.close();
服务器要响应多个Client的连接就需要用到多线程,每当有一个Client发出连接请求,都创建一个新的线程和这个Client进行专线通信。
下面是最基本的一个多线程处理Client请求的例子,先看主程序:
public class TCPServerTest{public static void main(String [] args) throws IOException{//1.创建TCP Server,监听10001号端口ServerSocket ss = new ServerSocket(10001);while(true){//2.等待客户端连接System.out.println("等待客户端连接...");Socket s = ss.accept(); System.out.println("连接成功!");//3.创建一个新线程和上面的客户端进行专线连接new Thread(new Server(s)).start();//4.打印连接信息,然后等待下一个连接System.out.println("新线程创建成功,客户端信息如下:");System.out.println(" 客户端IP: " + s.getInetAddress().getHostAddress()); System.out.println(" 客户端Port: " + s.getPort());System.out.println(); }}}
Server代码如下:
//服务器线程public class Server implements Runnable{private Socket s;//构造器,主线程传过来个socket,子线程才知道和哪个Socket连接public Server(Socket s){this.s = s;}public void run(){//程序执行到此说明服务器响应Client并新建Thread成功,获取输入输出流InputStreamips = s.getInputStream();OutputStreamops = s.getOutputStream();//将网络字节流转换为字符流,再包装成Buffer流BufferedReader br = new BufferedReader(new InputStreamReader(ips));String recvStr = null;while(true){//阻塞等待客户端输入一行数据recvStr = br.readLine();//如果客户端输入quit则退出循环,关闭连接if(recvStr.equalsIgnoreCase("quit")){break;}//把收到的数据回打给客户端String str = "服务器已收到,内容为:" + recvStr;ops.write(str.getBytes());}br.close();s.close();}
上面代码没有进行异常处理,这样编译是不通过的,但是为了简洁直观,这里只贴出了关键内容。
运行服务器程序,进行测试如下:
accept函数主要用于服务器端,默认会阻塞进程,直到有一个客户请求连接,建立好连接后,它返回的一个新的套接字Socket_New(),此后,服务器端即可使用这个新的套接字Socket_New()与该客户端进行通信,而ServerSocket 则继续用于监听其他客户端的连接请求。并且新的Socket_New是否为阻塞和非阻塞属性,与监听的Socket一样,监听的Socket为阻塞,则新的Socket_New也为阻塞,反之一样。
至此,我的困惑产生了,这个新的套接字 Socket_New与监听套接字ServerSocket是什么关系?它所代表的socket对象包含了哪些信息?Socket_New是否占用了新的端口与客户端通信?
设想一下,由于网站的服务器也是一种TCP服务器,使用的是80端口,并不会因客户端的连接而产生新的端口给客户端服务,该客户端依然是向服务器端的80端口发送数据,其他客户端依然向80端口申请连接。因此,可以判断,Socket_New并没有占用新的端口与客户端通信,依然使用的是与监听套接字socketfd_new一样的端口号。再说了,在一台机器中,端口的使用数量是65535,是有限的,不可能无限制的占用新端口来使用,那这么说,难道一个端口可以被两个socket对象绑定?当客户端发送数据过来的时候,究竟是与哪一个socket对象通信呢?
个人理解如下:
首先,一个端口肯定只能绑定一个socket。我认为,服务器端的端口在new ServerSocket(int port)的时候已经绑定到了监听套接字ss所描述的对象上,accept函数新创建的Socket_New对象其实并没有进行端口的占有,而是复制了ServerSocket ss的本地IP和端口号,并且记录了连接过来的客户端的IP和端口号。
那么,当客户端发送数据过来的时候,究竟是与哪一个socket对象通信呢?
客户端发送过来的数据可以分为2种,一种是连接请求,一种是已经建立好连接后的数据传输。由于TCP/IP协议栈是维护着一个接收和发送缓冲区的。在接收到来自客户端的数据包后,服务器端的TCP/IP协议栈应该会做如下处理: 1. 如果收到的是请求连接的数据包,则传给监听着连接请求端口的ServerSocket 套接字,进行accept处理;
2. 如果是已经建立过连接后的客户端数据包,则将数据放入接收缓冲区。
个人理解如下:
首先,一个端口肯定只能绑定一个socket。我认为,服务器端的端口在new ServerSocket(int port)的时候已经绑定到了监听套接字ss所描述的对象上,accept函数新创建的Socket_New对象其实并没有进行端口的占有,而是复制了ServerSocket ss的本地IP和端口号,并且记录了连接过来的客户端的IP和端口号。
那么,当客户端发送数据过来的时候,究竟是与哪一个socket对象通信呢?
客户端发送过来的数据可以分为2种,一种是连接请求,一种是已经建立好连接后的数据传输。由于TCP/IP协议栈是维护着一个接收和发送缓冲区的。在接收到来自客户端的数据包后,服务器端的TCP/IP协议栈应该会做如下处理: 1. 如果收到的是请求连接的数据包,则传给监听着连接请求端口的ServerSocket 套接字,进行accept处理;
2. 如果是已经建立过连接后的客户端数据包,则将数据放入接收缓冲区。
这样,当服务器端需要读取指定客户端的数据时,则可以利用socketfd_new 套接字通过recv或者read函数到缓冲区里面去取指定的数据(因为socketfd_new代表的socket对象记录了客户端IP和端口,因此可以鉴别)。
0 0
- JAVA网络编程之——TCP通信
- Java网络编程之TCP网络通信
- Java网络编程之TCP通信
- Java中网络通信编程之TCP通信
- 网络编程之TCP通信
- 网络通信之tcp编程
- JAVA网络编程:TCP通信
- JAVA网络编程-----TCP通信
- Java网络编程TCP通信
- java中的网络通信编程之TCP篇
- Linux网络编程——TCP通信
- 32、Java入门—网络编程之TCP编程
- Linux之—网络通信(TCP)
- Linux之—网络通信(TCP)
- Linux网络编程之TCP通信
- Window网络编程之TCP通信
- Linux编程网络之TCP通信
- Java中的TCP/UDP网络通信编程
- HTML 标签 <br> <br />
- Hadoop第六讲
- 黑马day07 自定义标签&简单标签
- ios九宫格
- Android工程中三种库的区别:Private 、Referenced、Dependency
- JAVA网络编程之——TCP通信
- Oracle RAC 环境下的连接管理
- Method类invoke方法的使用
- mysql批量插入数据方法
- 日语学习之沪江N3基础 20150626 -1
- C#如何获得文件的版本号
- HTML 标签 <hr> <hr />
- C++编译错误
- java快速排序法