快捷搜索:  as  MTU2MjI3NjIxOQ`

socket编程02: 一个简单的TCP服务器程序

TCP办事器法度榜样

下面是一个简单的TCP办事器法度榜样(server_v1.cpp),功能是将客户端发送的字符串转换成大年夜写后返回:

//server_v1.cpp

#include

#include

#include

#include

#include

#include

#include

#define MAXLINE 80

#define SERV_PORT 8000

int main(void)

{

sockaddr_in servaddr, cliaddr;

socklen_t cliaddr_len;

int listenfd, connfd;

char buf[MAXLINE];

char str[INET_ADDRSTRLEN];

int i;

ssize_t n;

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(SERV_PORT);

bind(listenfd, (struct sockaddr *)&servaddr,sizeof(servaddr));

listen(listenfd, 20);

printf("Accepting connections ...\n");

while (true)

{

cliaddr_len = sizeof(cliaddr);

connfd = accept(listenfd,

(struct sockaddr *)&cliaddr,

&cliaddr_len);

n = read(connfd, buf, MAXLINE);

printf("received from %s at PORT %d\n",

inet_ntop(AF_INET,

&cliaddr.sin_addr, str,sizeof(str)),

ntohs(cliaddr.sin_port));

for (i = 0; i

相关API

socket

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

socket()打开一个收集通讯端口,假如成功的话,就一个文件描述符,利用法度榜样可以像读写文件一样用read或write在收集上收发数据,假如socket()调用掉足则返回-1。对付IPv4, family参数指定为AF_INET。对付TCP协议, type参数为SOCK_STREAM,表示面向流的传输协议。假如是UDP协议,则type参数指定为SOCK_DGRAM,表示面向数据报的传输协议。protocol参数的先容从略,指定为0即可

bind

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

办事器法度榜样所监听的收集地址和端口号平日是固定不变的,客户端法度榜样得知办事器法度榜样的地址和端口号后就可以向办事器提议连接,是以办事器必要调用bind绑定一个固定的收集地址和端口号。 bind()成功返回0,掉败返回-1。bind()的感化是将参数sockfd和myaddr绑定在一路,使sockfd这个用于收集通讯的文件描述符监听myaddr所描述的地址和端口号。各参数意义如下:

myaddr: struct sockaddr *是一个通用指针类型

addrlen: 因为myaddr参数实际上可以吸收多种协议的sockaddr布局体,而它们的长度各不相同,以是必要第三个参数addrlen指定布局体的长度

法度榜样中对myaddr参数是这样初始化的:

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

servaddr.sin_port = htons(SERV_PORT);

首先将全部布局体清零,然后设置地址类型AF_INET,收集地址为INADDR_ANY,这个宏表示本地的随意率性IP地址,由于办事器可能有多个网卡,每个网卡也可能绑定多个IP地址,这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪个IP地址,端口号为SERV_PORT,代码中将其定义为8000

listen

int listen(int sockfd, int backlog);

范例的办事器法度榜样可以同时办事于多个客户端,当有客户端提议连接时,办事器调用的accept()返回并吸收这个连接,假如有大年夜量的客户端提议连接而办事器来不及处置惩罚,尚未accept的客户端就处于连接等待状态, listen()声明sockfd处于监听状态,并且最多容许有backlog个客户端处于连款待状态,假如接管到更多的连接哀求就轻忽。listen()成功返回0,掉败返回-1

accept

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

办事器调用accept()时假如还没有客户真个连接哀求,就壅闭等待直到有客户端连接上来。各参数意义如下:

cliaddr: cliaddr是一个传出参数, accept()返回时传出客户真个地址和端口号,假如给cliaddr参数传NULL,表示不关心客户真个地址。

addrlen: addrlen参数传入后会被改动,传入时是调用者供给的缓冲区cliaddr的长度,以避免缓冲区溢出问题,传出时是客户端地址布局体的实际长度(有可能没有占满调用者供给的缓冲区)

您可能还会对下面的文章感兴趣: