1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 第四章 基本TCP套接字编程 第五章 TCP客户/服务器程序实例

第四章 基本TCP套接字编程 第五章 TCP客户/服务器程序实例

时间:2023-04-01 16:31:10

相关推荐

第四章 基本TCP套接字编程 第五章 TCP客户/服务器程序实例

TCP客户与服务器进程之间发生的重大事件时间表

TCP服务器

socket() --- bind() --- listen() --- accept() --- read() --- write --- read() --- close

TCP客户

socket() --- connect() --- write() --- read() --- close()

套接字函数简介

int socket(int family, int type, int protocol);

指定要用的通信协议类型

int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);

客户用connect()来建立与TCP服务器的连接

int bind(int sockfd, const struct sockaddr *myaddr, scoklen_t addrlen);

把一个本地协议地址赋予一个套接字

int listen(int sockfd, int backlog);

设置套接字为被动套接字,指示内核接收向该套接字的连接请求

int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

由TCP服务器调用, 用来从已完成连接队列队头返回下一个已完成连接

pid_t fork(void);

产生子进程

int close(int sockfd);

关闭套接字, 并终止TCP连接

典型的并发服务器程序轮廓

pid_t pid;int listenfd, connfd;listenfd=Socket(...);Bind(listenfd, ...);Listen(listenfd,LISTENQ);for(;;){connfd=Accept(listenfd, ...);if((pid=Fork())==0){//如果是子进程Close(listenfd);//子进程关闭其监听套接字doit(connfd);//处理需求Close(connfd);//关闭子进程的已连接套接字exit(0);//子进程终止}Close(connfd);//父进程关闭已连接套接字}

TCP echo服务器程序

#include "unp.h"#include <time.h>void srv_echo(int sockfd){ssize_t n;char buf[1000];again:while((n=read(sockfd,buf,1000))>0)Writen(sockfd,buf,n);if(n<0 && errno==EINTR)goto again;else if(n<0)err_sys("srv_echo: read error");}intmain(int argc,char ** argv){int listenfd, connfd;pid_t childpid;socklen_t clilen;struct sockaddr_in cliaddr, servaddr;char buff[1000];listenfd=Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family=AF_INET;servaddr.sin_addr.s_addr=htonl(INADDR_ANY);servaddr.sin_port=htons(1234);Bind(listenfd, (SA*) &servaddr, sizeof(servaddr));Listen(listenfd, 100);for(;;){clilen=sizeof(cliaddr);connfd=Accept(listenfd, (SA*) &cliaddr, &clilen);printf("connection from %s , port %d\n",inet_ntop(AF_INET,&cliaddr.sin_addr, buff, sizeof(buff)),ntohs(cliaddr.sin_port));if((childpid=Fork())==0){Close(listenfd);srv_echo(connfd);exit(0);}Close(connfd);}}

TCP echo客户端程序

#include "unp.h"void cli_echo(FILE *fp, int sockfd){char sendline[1000], recvline[1000];while(Fgets(sendline,1000, fp)!=NULL){Writen(sockfd, sendline, strlen(sendline));if(Readline(sockfd, recvline, 1000)==0)err_quit("cli_echo: server terminated prematurely");Fputs(recvline, stdout);}}intmain(int argc, char **argv){int sockfd;struct sockaddr_in servaddr;if(argc!=2)err_quit("usage: tcpcli <IPaddress>");sockfd=Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family=AF_INET;servaddr.sin_port=htons(1234);Inet_pton(AF_INET,argv[1], &servaddr.sin_addr);Connect(sockfd, (SA*) &servaddr, sizeof(servaddr));cli_echo(stdin,sockfd);exit(0);}

这一章的API讲解非常有逻辑性, 讲解的过程可以看到这样设计的合理性

4.5 listen函数

当一个客户的SYN到达, 若服务器的相应监听套接字维护的队列已经满了, TCP就会忽略该分节, 也就是不发送RST.(这里的TCP指的是实现TCP的内核)

之所以这样设计有两点理由:

(1)这种情况是暂时的, TCP的正常重传机制会处理这个问题

(2)客户无法区分这个RST意思是 "该端口没有服务器在监听" 还是 "该端口有服务器在监听, 不过队列已满"

来自为知笔记(Wiz)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。