UNP学习第四章tcp

一、TCP简单流程图

因为对于server我已经写过一篇笔记了:http://www.cnblogs.com/ch122633/p/8315883.html

 所以我想再补充一些对于client的部分的笔记、和fork相关的总结。

二、connect函数:

#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
返回:0成功,-1出错
sockfd:套接字描述符
servaddr:套接口地址结构的指针
addrlen:该结构大小

客户在调用connect不必非调用bind,内核会选择源IP和临时端口。

connect函数会激发TCP三路握手过程,且仅在连接建立成功或出错时才返回。

bind函数:

#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *myaddr, sockelt_t addrlen);
返回:0成功,-1出错

listen函数

#include <sys/socket.h>

int listen(int sockfd, int backlog);
返回:0成功,-1出错

accept函数

#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
返回:非负描述字OK,-1出错

三、fork和exec函数

#include <unistd.h>

pid_t fork(void);
返回:在子进程中为0,在父进程中为子进程ID,-1出错

fork有两个典型应用:

1.进程创建自己的一个拷贝,当拷贝处理一个操作时,其他的拷贝可以执行其他任务。(网络)

2.一个进程想执行其他程序,犹豫创建新进程的唯一方法是调用fork,然后调用exec执行新程序。(shell)

#include <unistd.h>

int execl(const char *pathname, const char *arg0, ... /* (char *)0 */);
int execv(const char *pathname, char *const argv[]);
int execle(const char *pathname, const char *arg0, ...
                /* (char *)0, char *const envp[] */);
int execve(const char *pathname, char *const argv[], char *const envp[]);
int execlp(const char *filename, const char *arg0, ... /* (char *)0 */);
int execvp(const char *filename, char *const argv[]);
返回:-1出错,无返回成功

四、并发服务器

迭代服务器:大多数UDP服务器时迭代服务器,被单个客户长时间占用。

并发服务器:TCP服务器多使用,能同时服务多个客户。

    pid_t pid;
    int listenfd, connfd;

    listenfd = Socket(...);
        /* fill in sockaddr_in{} with server's well-known port */
    Bind(listenfd, ...);
    Listen(listenfd, LISTENQ);
    for(; ;) {
        connfd = Accept(listenfd, ...);             /* probably blocks */
        if((pid = Fork()) == 0) {
            Close(listenfd);                        /* child closes listening socket */
            doit(connfd);                           /* process the request */
            Close(connfd);                          /* done with this client */
            exit(0);                                /* child terminates */
        }
        Close(connfd);                              /* parent closes connected socket */
    }

在服务器阻塞于accept调用、连接请求从客户到达时客户和服务器的状态。

从accept返回后,连接被内核接受,新的套接口即connfd被创建,这是一个已连接套接口,可由此通过连接读、写数据。

并发服务器下一步是调用fork,此时listenfd和connfd都是在父进程和子进程共享的。

一般套接口也用close关闭,终止TCP连接

#include <unistd.h>

int close(int sockfd);
返回:0成功,-1出错

五、getsockname和getpeername函数

#include <sys/socket.h>

int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);
返回:0成功,-1出错

getsockname返回套接口关联的本地协议地址

getpeername返回套接口关联的远程协议地址

无欲速,无见小利。欲速,则不达;见小利,则大事不成。
原文地址:https://www.cnblogs.com/ch122633/p/8336557.html