基于java实现的一个hello/hi的简单的网络聊天程序

一、  Socket的工做流程java

Socket实质上提供了进程通讯的端点。进程通讯以前,双方首先必须各自建立一个端点,不然是没有办法创建联系并相互通讯的。正如打电话以前,双方必须各自拥有一台电话机同样。linux

对于一个功能齐全的Socket,都要包含如下结构,其工做流程包含如下四个基本步骤:算法

(1)    建立Socket编程

(2)    打开链接到Socket的输入/输出流windows

(3)    按照必定的协议对Socket进行读/写操做服务器

(4)    关闭Socket多线程

 

 

 

 

 

二、  java中的Socketsocket

java中的socket通讯主要经过两个已经封装好的类ServerSocket和Socket性能

socket一般开发的是客户端,用来让客户端经过端口号和IP地址链接到远程服务器。而ServerSocket实现的则是一个服务器应用,ServerSocket会一直等待客户端的请求,一旦得到了一个链接请求,就建立一个socket示例来与客户端进行通讯。ServerSocket会绑定一个固定的端口,知晓此端口和远程服务器的客服端能够经过IP地址和端口号来与远程客户端通讯,而服务端的端口则是随机的,在socket的应用中,咱们并不关心客户端的端口号。测试

 

三、  实现

Java中的socket在底层实现时最终是经过调用系统的socket来实现的,下面是java中的socket类的继承关系

 

 

 

 

从上图中能够看出ServerSocket就是针对SocketImpl的一个外观类。SocketImple是一个抽象类,而且这个抽象类SocketImpl实现了SocketOptions接口。

 

 

                               SocketOptions接口中声明的final属性

 

 

 

                                                     SocketImpl中的属性

 

 

四、  windows和Linux中的socket

windows在windows中socket方法返回的是SOCKET 一个宏定义

以下图所示

 

 

 

 

从上方代码看出他是u_int类型的别名,一个文件描述符为何是int呢?由于在windows编程下主要使用的是句柄,而句柄就是一串int数字这个数字标识这一个内存中的类(这里能够理解在系统中是键值对而这个int则是key,而他获取的对象则就是咱们使用accept或bind所须要的),暂时能够这么理解由于即便是内存也是键值对的map,各位读者暂时将这个int当作一个key值而调用其余socket方法都是须要这个key值的没有这个key是操做不了的。



linux在linux中socket方法比windows要直接,他直接返回的是int类型

以下图所示

 

 

上面都是针对linux和windows的讲解那么在java中是怎么描述的呢?

 

 

 

 

上面的代码是从SocketImpl中的bind方法的jni实现中的,能够看出他先获取了FileDescriptor对象也就是SocketImpl的fd,而后再根据FileDescriptor获取到他的fd咱们最终使用的文件描述符,而文件描述符也是int类型的,因此在java中的socket方法返回的也是int类型。



五、java中的socket和Linux的socket的区别

Socket是winsock里的原始套接字开发接口API,java是一门开发语言,而socket是一种通信标准的简称。Linux中的socket指的就是系统底层的socket,而像java这些开发语言,由于java自己是不带有socket通信底层实现的,因此他们所使用的socket只不过是对系统底层的Socket API进行了二次封装,面向开发人员,其本质上仍然和Linux底层的socket是同一个东西

 

六、java中的Socket用法

(1)  Socket的构造

Socket() 经过系统默认类型的 SocketImpl 建立未链接套接字

Socket(InetAddress address, int port) 建立一个流套接字并将其链接到指定 IP 地址的指定端口号。

Socket(String host, int port)

Socket(String host, int port, InetAddress localAddr, int localPort) 建立一个套接字并将其链接到指定远程主机上的指定远程端口。

 

(2)  方法摘要

 void

bind(SocketAddress bindpoint)
          将套接字绑定到本地地址。

 void

close()
          关闭此套接字。

 void

connect(SocketAddress endpoint)
          将此套接字链接到服务器。

 void

connect(SocketAddress endpoint, int timeout)
          将此套接字链接到服务器,并指定一个超时值。

 SocketChannel

getChannel()
          返回与此数据报套接字关联的惟一 SocketChannel 对象(若是有)。

 InetAddress

getInetAddress()
          返回套接字链接的地址。

 InputStream

getInputStream()
          返回此套接字的输入流。

 boolean

getKeepAlive()
          测试是否启用 SO_KEEPALIVE。

 InetAddress

getLocalAddress()
          获取套接字绑定的本地地址。

 int

getLocalPort()
          返回此套接字绑定到的本地端口。

 SocketAddress

getLocalSocketAddress()
          返回此套接字绑定的端点的地址,若是还没有绑定则返回 null。

 boolean

getOOBInline()
          测试是否启用 OOBINLINE。

 OutputStream

getOutputStream()
          返回此套接字的输出流。

 int

getPort()
          返回此套接字链接到的远程端口。

 int

getReceiveBufferSize()
          获取此 Socket 的 SO_RCVBUF 选项的值,该值是平台在 Socket 上输入时使用的缓冲区大小。

 SocketAddress

getRemoteSocketAddress()
          返回此套接字链接的端点的地址,若是未链接则返回 null。

 boolean

getReuseAddress()
          测试是否启用 SO_REUSEADDR。

 int

getSendBufferSize()
          获取此 Socket 的 SO_SNDBUF 选项的值,该值是平台在 Socket 上输出时使用的缓冲区大小。

 int

getSoLinger()
          返回 SO_LINGER 的设置。

 int

getSoTimeout()
          返回 SO_TIMEOUT 的设置。

 boolean

getTcpNoDelay()
          测试是否启用 TCP_NODELAY。

 int

getTrafficClass()
          为今后 Socket 上发送的包获取 IP 头中的流量类别或服务类型。

 boolean

isBound()
          返回套接字的绑定状态。

 boolean

isClosed()
          返回套接字的关闭状态。

 boolean

isConnected()
          返回套接字的链接状态。

 boolean

isInputShutdown()
          返回是否关闭套接字链接的半读状态 (read-half)。

 boolean

isOutputShutdown()
          返回是否关闭套接字链接的半写状态 (write-half)。

 void

sendUrgentData(int data)
          在套接字上发送一个紧急数据字节。

 void

setKeepAlive(boolean on)
          启用/禁用 SO_KEEPALIVE。

 void

setOOBInline(boolean on)
          启用/禁用 OOBINLINE(TCP 紧急数据的接收者) 默认状况下,此选项是禁用的,即在套接字上接收的 TCP 紧急数据被静默丢弃。

 void

setPerformancePreferences(int connectionTime, int latency, int bandwidth)
          设置此套接字的性能偏好。

 void

setReceiveBufferSize(int size)
          将此 Socket 的 SO_RCVBUF 选项设置为指定的值。

 void

setReuseAddress(boolean on)
          启用/禁用 SO_REUSEADDR 套接字选项。

 void

setSendBufferSize(int size)
          将此 Socket 的 SO_SNDBUF 选项设置为指定的值。

static void

setSocketImplFactory(SocketImplFactory fac)
          为应用程序设置客户端套接字实现工厂。

 void

setSoLinger(boolean on, int linger)
          启用/禁用具备指定逗留时间(以秒为单位)的 SO_LINGER。

 void

setSoTimeout(int timeout)
          启用/禁用带有指定超时值的 SO_TIMEOUT,以毫秒为单位。

 void

setTcpNoDelay(boolean on)
          启用/禁用 TCP_NODELAY(启用/禁用 Nagle 算法)。

 void

setTrafficClass(int tc)
          为今后 Socket 上发送的包在 IP 头中设置流量类别 (traffic class) 或服务类型八位组 (type-of-service octet)。

 void

shutdownInput()
          此套接字的输入流置于“流的末尾”。

 void

shutdownOutput()
          禁用此套接字的输出流。

 

七、javasocket编程-简单的hello/hi实现

基于服务器端实现的一个简单的聊天机器人,可支持多人同时聊天

效果以下:

                                       左边的是聊天服务器,右边两个是客户端

 

 

                                                            聊天恢复,第二个客户端下线

 

 

代码实现:

Demo_Receive.java:

 

 

 

Demo_Send.java:

 

 

 

 

Java中实现多线程主要有两种方法:

一、  继承Thread类,重写run()方法

二、  实现Runnable接口,重写Run()方法

这里使用的是第二种方法

 

 

做者:

SA19225475

 

 

 

 

 

参考:

https://www.jianshu.com/p/83d5598b9d3b   java中socket的实现

https://blog.csdn.net/weixin_34220834/article/details/85747263  

JAVA Socket编程和C++ Socket编程有什么不一样

https://blog.csdn.net/weixin_33829657/article/details/92413466  

JAVA中的socket的继承关系

相关文章
相关标签/搜索