首先,IP协议族决定了socket的地址类型,在通信中必须采用对应的地址。AF_INET(AF 表示 Adress Family)表示要用 ipv4 地址(32位)与端口号(16位)的组合。
然后,根据传输协议又分为:流式 Socket(SOCK_STREAM) 和数据报式 Socket(SOCK_DGRAM):
- 流式 SOCK_STREAM 是一种面向连接的Socket,针对于面向连接的TCP服务应用;
- 数据报式 SOCK_DGRAM 是一种无连接的Socket,对应于无连接的UDP服务应用;
先看一下 Java 的 Socket 通信。在 Java 环境下,Socket 编程主要就是指基于TCP/IP的网络编程,对应的 Socket API 主要是这两个类 Socket 和 ServerSocket。一个服务器端 socket 会对应多个 客户端 socket,这时就要配合多线程来实现,把 server.accept() 包在循环中,轮询监听客户端,然后每次建立连接的 socket 对象做参数建立新的线程即可。如果你只有一个客户端,那就无所谓了。
下面,通过一个最简单的例子来说明,因为文本通信是最常用的,所以这里介绍了文本通信的实现,当然也可以直接用二进制流,比如传文件。
Java 服务器 Socket
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class DataSocketServer { public static void main(String[] args) { try { ServerSocket server = new ServerSocket(5000); System.out.println("Server start!"); Socket socket = server.accept(); //阻塞等待, 直到一个客户端 socket过来 System.out.println("There comes a socket!"); BufferedReader in = new BufferedReader(new InputStreamReader( socket.getInputStream())); //输入,from 客户端 PrintWriter out = new PrintWriter(socket.getOutputStream()); //输出,to 客户端 System.out.println(in.readLine()); // 打印 客户 socket 发过来的字符,按行(\n,\r,或\r\n) out.println("Server reponse! ^_^ "); out.flush(); // to 客户端,输出 socket.close(); server.close(); System.out.println("Server end!"); } catch (IOException e) { e.printStackTrace(); } } }Java 客户端 Socket
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException; public class TestSocketClient { public static void main(String[] args) { try { Socket socket = new Socket("127.0.0.1", 5000); System.out.println("Client start!"); PrintWriter out = new PrintWriter(socket.getOutputStream()); // 输出,to 服务器 socket BufferedReader in = new BufferedReader(new InputStreamReader( socket.getInputStream())); // 输入, from 服务器 socket out.println("Client request! :-) "); out.flush(); // 刷缓冲输出,to 服务器 System.out.println(in.readLine()); // 打印服务器发过来的字符串 System.out.println("Client end!"); socket.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
Python 客户端 Socket (Python 3.4)
import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('localhost',5000)) print('Client start!') sock.send(bytes('客户端:)\n',encoding='utf-8')) # str 类型 -> bytes 类型,发送,\n 千万不要少了,因为前面的 server 是按行读取的 print(str(sock.recv(1024),encoding = 'utf-8')) # bytes 类型 -> str 类型,接受 sock.close() print('Client end!')
这里重点说明一下 Python 的 bytes 类型 和 str 类型的转换,在 Python3 中 文本和二进制数据做了更清晰的区分,文本总是 Unicode 为 str 类型,二进制则用 bytes 类型表示。清晰的划分更有利于程序的可读性和正确性。
当然,Server Socket 也可以用 Python 来写,先指定 协议和类型 socket.socket(family, type),然后绑定地址和端口, 然后进行监听,基本原理和上面是一样的。
地址:http://blog.csdn.net/thisinnocence