使用java的Socket实现客户端和服务器端之间的链接,实现客户端发送数据到服务器端,同时客户端能够接收到服务器端发来的数据。java
一、socket定义
网络上的两个程序经过一个双向的通讯链接实现数据的交换,这个链接的一端称为一个socket。创建网络通讯链接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员作网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通讯的能力。 Socket的英文原义是"孔"或"插座"。做为BSD UNIX的进程通讯机制,取后一种意思。一般也称做"套接字",用于描述IP地址和端口,是一个通讯链的句柄,能够用来实现不一样虚拟机或不一样计算机之间的通讯。在Internet上的主机通常运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不一样的端口对应于不一样的服务 简单来讲,咱们网络上的那些数据能够当作自来水管里的那些水,那如今服务器就是 自来水厂 而客户端就是你本身的家,那架设在外面的那些水管就是光纤,电话线等等传播网络信号的介质。为了更好的知足用户,这个时候水厂想把水给你送过去就会作个阀门而后经过这个阀门控制水的流量,同时你本身家也一样装一个阀门来控制。程序员
二、java Socket编程通常步骤:
- 服务器实例化一个 ServerSocket 对象,表示经过服务器上的端口通讯。
- 服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,直到客户端链接到服务器上给定的端口。
- 服务器正在等待时,一个客户端实例化一个 Socket 对象,指定服务器名称和端口号来请求链接。
- Socket 类的构造函数试图将客户端链接到指定的服务器和端口号。若是通讯被创建,则在客户端建立一个 Socket 对象可以与服务器进行通讯。
- 在服务器端,accept() 方法返回服务器上一个新的 socket 引用,该 socket 链接到客户端的 socket。 链接创建后,经过使用 I/O 流在进行通讯,每个socket都有一个输出流和一个输入流,客户端的输出流链接到服务器端的输入流,而客户端的输入流链接到服务器端的输出流。
TCP 是一个双向的通讯协议,所以数据能够经过两个数据流在同一时间发送.如下是一些类提供的一套完整的有用的方法来实现 socket。编程
三、代码实现
客户端
public class ClientDemo { public static void main(String[] args) throws IOException { //建立发送端的Socket对象 Socket s = new Socket("172.16.79.129",8888); //获取输出流 OutputStream os = s.getOutputStream(); Scanner scanner = new Scanner(System.in); System.out.println("请输入你要发送的数据:"); String string = scanner.nextLine(); os.write(string.getBytes()); //获取输入流 InputStream is = s.getInputStream(); byte[] bys = new byte[1024]; int len = is.read(bys); String client = new String(bys, 0 , len); System.out.println("server发送来的数据:"+client); //释放资源 s.close(); } }
服务端
public class SeverDemo { public static void main(String[] args) throws IOException { //建立接收端的Socket对象 ServerSocket ss = new ServerSocket(8888); //监听客户端的链接 Socket s = ss.accept(); //获取输入流,读取显示在控制台 InputStream is = s.getInputStream(); byte[] bys = new byte[1024]; int len = is.read(bys); String server = new String(bys, 0 , len); System.out.println( "server接收到client发送的信息:" + server); //获取输出流 OutputStream os = s.getOutputStream(); os.write("hi".getBytes()); //释放资源 s.close(); } }
执行结果
这里有个问题,这个通讯过程全是java本身完成的吗?答案是否认的!java通讯程序最底层仍是调用了操做系统的Socket函数,才能完成通讯!那么接下来咱们将介绍Linux下TCP通讯过程!服务器
四、TCP通讯过程
工做过程以下:
首先服务器启动,经过调用Socket()创建一个套接字;而后调用bind()将该套接字和本地网络地址联系在一块儿,再调用listen()使套接字作好侦听的准备,并规定它的请求队列的长度;以后就调用accept()来接收链接。客户在创建套接字后就可调用connect()和服务器创建链接。链接一旦创建,客户和服务器之间就能够经过调用read()和write()来发送和接收数据。最后,待数据传送结束后,双方调用close()关闭套接字。网络
使用到的一些函数:
一、使用Socket()建立套接字 Socket()系统调用建立一个用于网络通讯的套接字,并返回该套接字的整数描述符。dom
#include <sys/socket.h int socket(int domain, int type, int protocol)
domain: 协议域, 决定了 socket 的地址类型, 在通讯中必须采用对应的地址。 type: 指定 socket 类型。 protocol: 指定协议。socket
二、绑定本地地址 bind()函数将Socket与本机上的一个端口相关联,随后便可在该端口监听服务器请求。函数
1 #include <sys/socket.h 2 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
sockfd: 是由socket()函数返回的套接字描述符 sa: 是一个指向 struct sockaddr 的指针,包括有关地址的信息,如名称、端口和IP地址 addrlen: 是套接字地址的长度spa
三、listen()函数 使用listen()函数将套接字设置为监听模式,以等待链接请求。操作系统
1 #include <sys/socket.h> 2 int listen(int sockfd, int backlog);
sockfd: 即 socket 描述字, 由 socket() 函数建立。
backlog: 指定在请求队列中的最大请求数, 进入的链接请求将在队列中等待 accept() 它们。
四、accept()函数 请求到来后,使用accept()函数接收链接请求。
1 #indclude <sys/socket.h> 2 int accept(int listenfd, struct sockaddr *addr, int *addrlen);
listenfd: 服务器的 socket 描述字, 由 socket() 函数建立。
addr: 一个 const struct sockaddr 指针, 用来存放提出链接请求客户端的主机的信息
addrlen: 协议地址的长度, 若是是 ipv4 的 TCP 链接, 通常为 sizeof(sockaddr_in)。
五、connect函数 由客户端调用, 与目的服务器的套接字创建一个链接。
1 #include <sys/socket.h> 2 int connect(int clientfd, const struct sockaddr *addr, socklen_t addrlen);
clientfd: 目的服务器的 socket 描述 addr: 一个 const struct sockaddr 指针, 包含了目的服务器 IP 和端口 addrlen: 协议地址的长度, 若是是 ipv4 的 TCP 链接, 通常为 sizeof(sockaddr_in);
六、close()函数 在数据传输完成以后, 手动关闭链接。
1 #include <sys/socket.h> 2 #include <unistd.h> 3 int close(int fd);
fd: 须要关闭的链接 socket 描述符
总结: Linux中的socket指的就是系统底层的socket,而像java这些开发语言,由于java自己是不带有socket通信底层实现的,因此他们所使用的socket只不过是对系统底层的Socket API进行了二次封装,面向开发人员,其本质上仍然和Linux底层的socket是同一个东西