svnadmin create --fs-type fsfs /data/svn
svn ls file:///data/svn
svn mkdir file:///data/svn/foo -m 'create dumb directory'
svn rm file:///data/svn/foo -m 'rm dumb diretory'
svn import project file:///data/svn/project/trunk -m 'initial import'
export SVN_EDITOR='vim'
svn checkout http://192.168.92.120/svn/sage/branches/RockStar
svn checkout file:///data/svn
svn checkout -r 4 file:///data/svn xyz
svn add file
svn delete file
svn commit -m 'log msg' [-N] [-no-unlock] PATH
svn lock -m 'lock msg' [--force] PATH
svn unlock
svn revert file
svn revert -R dir
svn diff -r BASE
svn diff -r 100:101 PATH
svn info
svn status [-v] PATH
svn log file:///data/svn/
svn update -r 100 PATH
svn upgrade
svn --version
changelist
Undoubtedly, one of the most misunderstood aspects of TCP with regard to network programming is its TIME_WAIT state. We can see in Figure 2.4 that the end that performs the active close goes through this state. The duration that this endpoint remains in this state is twice the maximum segment lifttime(MSL), sometimes called 2MSL.
Every implementation of TCP must choose a value for the MSL. The recommended value in RFC 1122 [Braden 1989] is 2 minutes, although Berkeley-derived implementations have traditionally used a value of 30 seconds instead. This means the duration of the TIME_WAIT state is between 1 and 4 minutes. The MSL is the maximum amount of time that any given IP datagram can live in a network. We know this time is bounded because every datagram contains an 8-bit hop limit with a maximum value of 255. Although this is a hop limit and not a true time limit, the assumption is made that a packet with the maximum hop limit of 255 cannot exist in a network for more than MSL seconds.
The way in which a packet gets “lost” in a network is usually the result of routing anomalies. A router crashes or a link between two routers goes down and it takes the routing protocols seconds or minutes to stabilize and find an alternate path. During that time period, routing loops can occur(router A sends packets to router B, and B sends them back to A) and packets can get caught in these loops. In the meantime, assuming the lost packet is a TCP segment, the sending TCP times out and retransmits the packet, and the retransmitted packet gets to the final destination by some alternate path. But sometime later(up to MSL seconds after the lost packet started on its journey), the routing loop is corrected and the packet that was lost in the loop is sent to the final destination. This original packet is called a lost duplicate or a wandering duplicate. TCP must handle these duplicates.
There are two reasons for the TIME_WAIT state:
To implement TCP’s full-duplex connection termination reliability
To allow old duplicate segments to expire in the network
The first reason can be explained by looking at Figure 2.5 and assuming that the final ACK is lost. The server will resend its final FIN, so the client must maintain state information, allowing it to resend the final ACK. If it did not maintain this information, it would respond with an RST (a different type of TCP segment), which would be interpreted by the server as an error. If TCP is performing all the network necessary to terminate both directions of data flow cleanly for a connection (its full-duplex close), then it must correctly handle the loss of any these four segments. This example also shows why the end that performs the active close is the end that remains in the TIME_WAIT state: because that end is the one that might have to retransmit the final ACK.
To understand the second reason for the TIME_WAIT state, assume we have a TCP connection between 12.106.32.254 port 1500 and 206.168.112.219 port 21. This connection is closed and then sometime later, we establish another connection between the same IP addresses and ports: 12.106.32.254 port 1500 and 206.168.112.219 port 21. This latter connection is called an incarnation of the previous connection since the IP addresses the ports are the same. TCP must prevent old duplicates from a connection from reappearing at some later time an being misinterpreted as belonging to a new incarnation of the same connection. To do this, TCP will not initial a new incarnation of a connection that is currently in the TIME_WAIT state. Since the duration of the TIME_WAIT state is twice of the MSL, this allows MSL seconds for a packet in one direction to be lost, and another MSL seconds for the reply to be lost. By enforcing this rule, we are guaranteed that when we successfully establish a TCP connection, all old duplicates from previous incarnations of the connection have expired in the network.
以上摘自 «Unix Network Programming Vol 1» 2.7节。
为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
这是因为:虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文,并保证于此。
下面算法的时间复杂度是____
int foo(int n) {
if (n <= 1) {
return 1;
}
return n * foo(n - 1);
}
我们要做的第一步便是确定关键操作,这里的关键操作显然是if语句,那么我们只需要判断if语句执行的次数即可。首先我们看到这是一个递归过程:foo会不断的调用自身,直到foo的实参小于等于1,foo就会返回1,之后便不会再执行if语句了。由此我们可以知道,if语句调用的次数为n次,所以时间复杂度为O(n)。
以下函数的时间复杂度为____
void recursive(int n, int m, int o) {
if (n <= 0) {
printf("%d, %d\n", m, o);
} else {
recursive(n - 1, m + 1, o);
recursive(n - 1, m, o + 1);
}
}
首先,它的关键操作时if语句,因此我们只需判断出if语句的执行次数即可。以上函数会在n > 0的时候不断递归调用自身,我们要做的是判断在到达递归的base case(即n <= 0)前,共执行了多少次if语句。我们假设if语句的执行次数为T(n, m, o),那么我们可以进一步得到:T(n, m, o) = T(n-1, m+1, o) + T(n-1, m, o+1) (当n > 0时)。我们可以看到base case与参数m, o无关,因此我们可以把以上表达式进一步简化为T(n) = 2T(n-1)。
由此我们可得:
T(n) = 2T(n-1)
= (2^2) * T(n-2)
= (2^3) * T(n-3)
= ...
而很明显T(1) = 2
所以:
T(1) = 2
T(2) = 2T(n-1) = 2 * T(1) = 2 * 2 = 2^2
T(3) = (2^2) * T(n-2) = (2^2) * T(1) = 2^3
T(4) = (2^3) * T(n-3) = (2^3) * T(1) = 2^4
...
T(n) = 2^n
所以我们可以得到以上算法的时间复杂度为O(2^n)。
如下程序的时间复杂度为____(其中m > 1,e > 0)
x = m;
y = 1;
while (x - y > e) {
x = (x + y) / 2;
y = m / x;
}
print(x);
以上算法的关键操作即while语句中的两条赋值语句,我们只需要计算这两条语句的执行次数即可。我们可以看到,当x - y > e时,while语句体内的语句就会执行,x = (x + y) / 2使得x不断变小(当y«x时,执行一次这个语句会使x变为约原来的一半),假定y的值固定在1,那么循环体的执行次数即为~logm,而实际情况是y在每次循环体最后都会被赋值为m / x,这个值总是比y在上一轮循环中的值大,这样一来x-y的值就会更小,所以以上算法的时间复杂度为O(logm)。
假设y一直为1,那么:
执行的次数 | x的大小 |
0 | m |
1 | m/2 |
2 | m/(2^2) |
3 | m/(2^3) |
n | m/(2^n) |
m/(2^n) > 1
令 m/(2^n) = 1
则 n = log(m) 以2为基
假设某算法的计算时间可用递推关系式T(n) = 2T(n/2) + n,T(1) = 1表示,则该算法的时间复杂度为____
T(1) = 1
T(n) = 2T(n/2) + n
T(n/2) = 2T(n/4) + n/2
T(n/4) = 2T(n/8) + n/4
...
所以:
T(n) = 2T(n/2) + n
= (2^2) * T(n/(2^2)) + 2*n
= (2^3) * T(n/(2^3)) + 3*n
= ...
T(1) = 1
T(2) = 2T(n/2) + n = 2T(1) + 2 = 4
T(4) = (2^2) * T(n/(2^2)) + 2*n = (2^2) * T(1) + 2*4 = 12
T(8) = (2^3) * T(n/(2^3)) + 3*n = (2^3) * T(1) + 3*8 = 32
...
T(n) = (2^k) + k*n (k = logn)
= n + nlogn
所以时间复杂度为 O(nlogn)
T(1) = 1
T(n) = T(n-1)
时间复杂度: O(1)
T(1) = 1
T(n) = T(n-1) + 1
时间复杂度: O(n)
T(1) = 1
T(n) = 2T(n-1)
时间复杂度: O(2^n)
T(1) = m
T(n) = T(n-1) / 2
时间复杂度: O(logm)
T(1) = 1
T(n) = 2*T(n/2) + n
时间复杂度: O(n + nlogn) = O(nlogn)
#include <iostream>
#include <stdio.h>
using namespace std;
class CVirtualBase
{
public:
virtual void vPureVirtualFunc() = 0;
virtual void vVirtualFunc() {
printf("CVirtualBase::vVirtualFunc()\n");
}
void vFunc() {
printf("CVirtualBase::vFunc()\n");
}
};
class CSubVirtual : CVirtualBase
{
public:
void vPureVirtualFunc() {
printf("CSubVirtual::vPureVirtualFunc()\n");
}
void vVirtualFunc() {
printf("CSubVirtual::vVirtualFunc()\n");
}
void vFunc() {
printf("CSubVirtual::vFunc()\n");
}
};
int main()
{
//有virtual, p->fun() 取决于右边
//没有virtual, p->fun() 取决于左边
CVirtualBase * instance = (CVirtualBase *) new CSubVirtual();
instance->vPureVirtualFunc(); //CSubVirtual::vPureVirtualFunc()
instance->vVirtualFunc(); //CSubVirtual::vVirtualFunc()
instance->vFunc(); //CVirtualBase::vFunc()
getchar();getchar();
return 0;
}
#include <stdio.h>
#define B2IL(b) (((b)[0] & 0xFF) | (((b)[1] << 8) & 0xFF00) | (((b)[2] << 16) & 0xFF0000) | (((b)[3] << 24) & 0xFF000000))
#define B2IU(b) (((b)[3] & 0xFF) | (((b)[2] << 8) & 0xFF00) | (((b)[1] << 16) & 0xFF0000) | (((b)[0] << 24) & 0xFF000000))
int main()
{
char acWord[1024] = {0};
acWord[0] = 'a';
acWord[1] = 'b';
acWord[2] = 'c';
acWord[3] = 'd';
printf("acWord: %s\n", acWord);
printf("acWord: %c %c %c %c\n", acWord[0], acWord[1], acWord[2], acWord[3]);
printf("acWord: %d %d %d %d\n", acWord[0], acWord[1], acWord[2], acWord[3]);
printf("acWord: %x %x %x %x\n", acWord[0], acWord[1], acWord[2], acWord[3]);
printf("\n");
char *pcWord = acWord;
printf("pcWord: %s\n", pcWord);
printf("pcWord: %c %c %c %c\n", pcWord[0], pcWord[1], pcWord[2], pcWord[3]);
printf("pcWord: %d %d %d %d\n", pcWord[0], pcWord[1], pcWord[2], pcWord[3]);
printf("pcWord: %x %x %x %x\n", pcWord[0], pcWord[1], pcWord[2], pcWord[3]);
printf("#define B2IL(b) (((b)[0] & 0xFF) | (((b)[1] << 8) & 0xFF00) | (((b)[2] << 16) & 0xFF0000) | (((b)[3] << 24) & 0xFF000000))\n");
printf("#define B2IU(b) (((b)[3] & 0xFF) | (((b)[2] << 8) & 0xFF00) | (((b)[1] << 16) & 0xFF0000) | (((b)[0] << 24) & 0xFF000000))\n");
printf("B2IL(pcWord): %x\n", B2IL(pcWord));
printf("B2IU(pcWord): %x\n", B2IU(pcWord));
return 0;
}
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")
#define MAX_FILE_NAME_LEN 256
#define utf8(str) WcharToChar(L##str)
const char * WcharToChar(const wchar_t * pwcStr)
{
static char acBuf[1024];
WideCharToMultiByte(CP_UTF8, 0, pwcStr, -1, acBuf, sizeof(acBuf), NULL, NULL);
return acBuf;
}
const wchar_t * CharToWchar(const char * pcStr)
{
static wchar_t awcBuf[1024];
MultiByteToWideChar(CP_UTF8, 0, pcStr, -1, awcBuf, sizeof(awcBuf));
return awcBuf;
}
int main()
{
char acPathBuf[MAX_FILE_NAME_LEN] = "F:\\share\\git\\mdgsf";
printf("%s\n", acPathBuf);
/** convert from local to unicode **/
DWORD dErrCode = 0;
wchar_t acUnicode[MAX_FILE_NAME_LEN] = {0};
if(0 == MultiByteToWideChar(CP_ACP, 0, (LPCSTR)acPathBuf, -1, (LPWSTR)acUnicode, MAX_FILE_NAME_LEN))
{
dErrCode = GetLastError();
printf("convert to unicode fail, error code: %d\n", dErrCode);
return -1;
}
/** convert from unicode to utf-8 **/
char acUTF8[MAX_FILE_NAME_LEN] = {0};
if(0 == WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)acUnicode, -1, (LPSTR)acUTF8, MAX_FILE_NAME_LEN, NULL, NULL))
{
dErrCode = GetLastError();
printf("convert to utf-8 fail, error code: %d\n", dErrCode);
return -1;
}
printf("%s\n", acUTF8);
getchar();getchar();
return 0;
}