1,socket 原理
Socket 实质上提供了进程通信的端点. 进程通信之前, 双方首先必须各自创建一个端点, 否则是没有办法建立联系并相互通信的. 正如打电话之前, 双方必须各自拥有一台电话机一样.
套接字之间的连接过程可以分为三个步骤: 服务器监听, 客户端请求, 连接确认.
1, 服务器监听: 是服务器端套接字并不定位具体的客户端套接字, 而是处于等待连接的状态, 实时监控网络状态.
2, 客户端请求: 是指由客户端的套接字提出连接请求, 要连接的目标是服务器端的套接字. 为此, 客户端的套接字必须首先描述它要连接的服务器的套接字, 指出服务器端套接字的地址和端口号, 然后就向服务器端套接字提出连接请求.
3, 连接确认: 是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求, 它就响应客户端套接字的请求, 建立一个新的线程, 把服务器端套接字的描述发给客户端, 一旦客户端确认了此描述, 连接就建立好了. 而服务器端套接字继续处于监听状态, 继续接收其他客户端套接字的连接请求.
2, 基于 java 中的 socket 编程
客户端:
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.NET.Socket;
- public class client {
- public static void main(String args[]) throws Exception {
- // 连接本地主机, 端口自设, 与服务端一致即可
- String host = "127.0.0.1";
- int port = 23333;
- // 通过 socket 与服务端建立连接
- Socket socket = new Socket(host, port);
- if(socket.isConnected()){
- System.out.println("Connected!");
- }
- // 将要发送的信息写入输出流
- OutputStream output = socket.getOutputStream();
- String sent = "hello";
- socket.getOutputStream().write(sent.getBytes("UTF-8"));
- // 关闭客户端的输出流(单向, 并未关闭 socket)
- socket.shutdownOutput();
- System.out.println("sent message to server:" + sent);
- // 读取从 server 返回的输入流
- InputStream input = socket.getInputStream();
- byte[] bytes = new byte[1024];
- int len;
- StringBuilder get = new StringBuilder();
- while ((len = input.read(bytes)) != -1) {
- get.append(new String(bytes, 0, len,"UTF-8"));
- }
- System.out.println("get message from server:" + get);
- // 关闭 socket
- input.close();
- output.close();
- socket.close();
- }
- }
服务器端:
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.NET.ServerSocket;
- import java.NET.Socket;
- public class server {
- public static void main(String[] args) throws Exception {
- // 监听指定的端口, 阻塞直至客户端连接此端口
- int port = 23333;
- ServerSocket server = new ServerSocket(port);
- System.out.println("server is waiting...");
- Socket socket = server.accept();
- System.out.println("Connected!");
- // 读取从客户端返回的输入流, 至尾端时返回 - 1
- InputStream input = socket.getInputStream();
- byte[] bytes = new byte[1024];
- int len;
- StringBuilder get = new StringBuilder();
- while ((len = input.read(bytes)) != -1) {
- get.append(new String(bytes, 0, len, "UTF-8"));
- }
- System.out.println("get message from client:" + get);
- OutputStream output = socket.getOutputStream();
- String sent = "Hi there";
- output.write(sent.getBytes("UTF-8"));
- System.out.println("sent message to client:" + sent);
- // 关闭 socket 与服务器端
- input.close();
- output.close();
- socket.close();
- server.close();
- }
- }
实验结果:
首先运行服务器
然后运行客户端
然后服务器端结果
3, 程序思路
(1)建立一个服务器 ServerSocket, 并同时定义好 ServerSocket 的监听端口;
(2)ServerSocket 调用 accept()方法, 使之处于阻塞.
(3)创建一个客户机 Socket, 并设置好服务器的 IP 和端口.
(4)客户机发出连接请求, 建立连接.
(5)分别取得服务器和客户端 ServerSocket 和 Socket 的 InputStream 和 OutputStream.
(6) 利用 Socket 和 ServerSocket 进行数据通信.
4,Linux 中的 socket 与 Windows 中 socket 文件之间的区别.
socket 作为套接字, 能够对数据进行包装后进行发送, socket 本质是一个文件.
Linux 中是将 socket 文件视为普通文件, 而在 Windows 中将 socket 文件看成是一个网络连接来对待, 因此需要调用专门针对 socket 而设计的数据传输函数.
在 Windows 操作系统中, 使用 native 标注的本地方法在编译时会生成一个动态链接库 (.dll 文件) 为 JAVA 语言提供相应的本地服务.
int socket(itn domain, int type, int protocol); // 创建一个套接字 | |
int bind(int sockfd, const struct sockaddr *addr, socklen_t addelen);// 将套接字绑定到地址上 | |
int listen(int sockfd, int backlog); // 监听连接 | |
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);// 接收一个连接请求 |
来源: http://www.bubuko.com/infodetail-3324678.html