所以我想了解 PuTTY 如何实施 SCP 并有几个问题。
首先,这是一个较旧且(恕我直言)更易于阅读的 PuTTY SCP 实现版本的副本:
https://github.com/Yasushi/putty/blob/4eeae4a39bc9faf539b8f819c12b1d1b9f22fc86/scp.c
这是发送数据的函数:
int scp_send_filedata(char *data, int len)
{
int bufsize = back->send(data, len);
/*
* If the network transfer is backing up - that is, the remote
* site is not accepting data as fast as we can produce it -
* then we must loop on network events until we have space in
* the buffer again.
*/
while (bufsize > MAX_SCP_BUFSIZE) {
if (!scp_process_network_event())
return 1;
bufsize = back->sendbuffer();
}
return 0;
}
这是 scp_process_network_event:
static int scp_process_network_event(void)
{
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(scp_ssh_socket, &readfds);
if (select(1, &readfds, NULL, NULL, NULL) < 0)
return 0; /* doom */
select_result((WPARAM) scp_ssh_socket, (LPARAM) FD_READ);
return 1;
}
那么 scp_process_network_event 执行 select() 系统调用,阻塞直到写入操作不会阻塞?
我在想 back->sendbuffer 和 back->send 对应于:
https://github.com/Yasushi/putty/blob/4eeae4a39bc9faf539b8f819c12b1d1b9f22fc86/ssh.c
/*
* Called to send data down the Telnet connection.
*/
static int ssh_send(char *buf, int len)
{
if (s == NULL || ssh_protocol == NULL)
return 0;
ssh_protocol(buf, len, 0);
return ssh_sendbuffer();
}
/*
* Called to query the current amount of buffered stdin data.
*/
static int ssh_sendbuffer(void)
{
int override_value;
if (s == NULL || ssh_protocol == NULL)
return 0;
/*
* If the SSH socket itself has backed up, add the total backup
* size on that to any individual buffer on the stdin channel.
*/
override_value = 0;
if (ssh_throttled_all)
override_value = ssh_overall_bufsize;
if (ssh_version == 1) {
return override_value;
} else if (ssh_version == 2) {
if (!mainchan || mainchan->closes > 0)
return override_value;
else
return override_value + bufchain_size(&mainchan->v.v2.outbuffer);
}
return 0;
}
不过我对此并不完全确定,而且我也不太擅长 C :(
无论如何,我并不完全清楚 bufsize 应该是什么。
有任何想法吗?
谢谢!