Internet 领域:TCP,UDP,SSL 和 TLS

PHP 3,PHP 4,PHP 5。 ssl://& tls://自 PHP 4.3 起可用。

sslv2://& sslv3://自 PHP 5.0.2 起可用。

Note: 如果没有指定传输器,则假定为 tcp://

  • 127.0.0.1
  • fe80::1
  • www.example.com
  • tcp://127.0.0.1
  • tcp://fe80::1
  • tcp://www.example.com
  • udp://www.example.com
  • ssl://www.example.com
  • sslv2://www.example.com
  • sslv3://www.example.com
  • tls://www.example.com

Internet 领域套接字在目标地址中还期望有一个端口号。在 fsockopen()中在第二个参数中指定,这样就不会影响传输器的 URL。然而在 stream_socket_client()和相关的函数中是用传统的 URL,端口号在传输器 URL 后面以冒号分隔而指定。

  • tcp://127.0.0.1:80
  • tcp://[fe80::1]:80
  • tcp://www.example.com:80

Note: 带端口号的 IPv6 数字地址
在上面的第二个例子中,IPv4 和主机名的例子只加了一个冒号和端口号,但 IPv6 的地址被放在方括号中: [fe80::1]。这是为了将 IPv6 地址中的冒号和用来分隔端口号的冒号区别开来。

ssl://tls://传输器(仅在 openssl 支持已编译入 PHP 后可用)是 tcp://传输器加入 SSL 加密后的扩展。在 PHP 4.3.0 中 OpenSSL 支持必须被静态编译入 PHP,在 PHP 5.0.0 中可以编译为模块或者静态的。

ssl://将根据远程服务器的兼容性和参数设置尝试与之建立 SSL V2 或 SSL V3 链接 sslv2://sslv3://将明确的选择 SSL V2 或 SSL V3 协议进行连接。

ssl://tls://传输器的上下文选项(自 PHP 4.3.2 起)
名称 用法 默认值
verify_peer &true; 或 &false;。用于 SSL 证书请求验证。 &false;
allow_self_signed &true; 或 &false;。允许自签名的证书。 &false;
cafile 本地文件系统中证书授权机构文件的位置,应和 verify_peer上下文选项一起使用来认证远端的身份。  
capath 如果没有指定 cafile或者如果该处没找到证书,则在 capath指定的目录中搜索相配的证书。 capath必须是一个正确的被散列化的证书目录。  
local_cert 文件系统中本地证书文件的路径。必须是一个用 PEM 编码并包含你的证书和私人密钥的文件。可以选择包括发行者的证书链。  
passphrase 你的 local_cert文件编码的 passphrase。  
CN_match 所期待的 Common Name。PHP 能进行有限的通配符匹配。如果 Common Name 与此不匹配,连接尝试会失败。  

Note: 因为 ssl:// https:// ftps:// 封装协议的底层传输器,适用于 ssl://的任何上下文选项也适用于 https://ftps://

User Contributed Notes

christian at lantian dot eu 17-Sep-2013 12:46
@pablo dot livardo  :  I think that the problem you found is caused by the difference between the client/server encryption methods used.

The 465 port is used for SMTPS, and the server starts the encryption immediately it receives your connection. So, your code will work.

The 587 port is used for Submission (MSA or Mail Submission Agent) which works like the port 25. The server accepts your connection and doesn't activate the encryption. If you want an encrypted connection on the port 587, you must connect on it without encryption, you must start to dialog with the server (with EHLO) and after that you must ask the server to start the encrypted connection using the STARTTLS command. The server starts the encryption and now you can start as well the encryption on your client.

So, in few words, you can not use :

<?php $fp = fsockopen("tls://mail.example.com", 587, $errno, $errstr);  ?> 

but you can use:

 <?php $fp = stream_socket_client("mail.example.com:587", $errno, $errstr); ?> 

and after you send the STARTTLS command, you can enable the crypto:

<?php stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT); ?>

P.S. My previous note on this page was totally wrong, so I ask the php.net admin to remove it.

:)
christian at lantian dot eu 16-Sep-2013 08:17
@pablo dot livardo  :  I think that the problem you found is caused by the difference between the client/server encryption methods used.

You tried to access the port 587 using TLS encryption, but the server uses the SSLv3 encryption on this port.

You can communicate with the Google server on port 465 because on this port the communication is encrypted using TLS and your client is configured to recognize the TLS.

So, if you want to connect on the Google server over the port 587, you simply must write:

<?php
$fp
= fsockopen("ssl://mail.example.com", 587, $errno, $errstr);
?>

instead of:

<?php
$fp
= fsockopen("tls://mail.example.com", 587, $errno, $errstr);
?>

:)
stefan at example dot com 20-Aug-2010 05:42
Actually, PHP is very able to start with an unencrypted connection and then switch to an encrypted one - refer to http://php.net/stream_socket_enable_crypto .
pablo dot livardo at gmail dot com 09-Dec-2009 09:56
I've been having a problem with a TLS connection.

<?php
$fp
= fsockopen("tls://mail.example.com", 587, $errno, $errstr);
?>

Which gives me an error of:

SSL operation failed with code 1. OpenSSL Error messages: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

I believe this is caused by PHP not being able to start with an unencrypted connection and then switch to encryption even though the functionality is built into OpenSSL.

For Google Mail users you can avoid this by using port 465 instead of 587.