#include "include/net.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
int main()
{
/**
* 为了执行网络I/O,一个进程必须做的第一件事情就是创建一个socket函数
* int socket(int family, int type, int protocol);
* family 表示协议族 AF_INET(IPv4协议)、AF_INET6(IPv6协议)、AF_LOCAL(Unix域协议)、
* AF_ROUTE(路由套接字)、AF_KEY( 密钥套接字)
* type 表示套接字类型 SOCK_STREAM(字节流套接字)、SOCK_DGRAM(数据报套接字)、
* SOCK_SEQPACKET(有序分组套接字)、SOCK_ROW(原始套接字)
* protocol 表示传输协议 IPPROTO_TCP(TCP传输协议)、IPPROTO_UDP(UDP传输协议)、
* IPPROTO_SCTP(SCTP传输协议)
* 若成功返回非负描述符,若出错返回-1
*/
printf("1,\n");
int listenfd = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); //IPv4, 字节流套接字, tcp协议
if(listenfd < 0){
printf("socket error \n");
return -1;
}
printf("socket success \n");
/**
* struct sockaddr_in {
* uint8_t sin_len; //结构体长度
* sa_family_t sin_family; //AF_INET
* in_port_t sin_port; //端口(16-bie)
* struct in_addr sin_addr; //IPv4地址(32-bit)
* char sin_zero[8]; //冗余,设置0即可
*/
struct sockaddr_in svraddr;/*声明一个变量,类型为协议地址类型*/
svraddr.sin_family = AF_INET;/*使用IPv4协议*/
svraddr.sin_port = htons(80);/*监听8887端口*/
svraddr.sin_addr.s_addr = htonl(INADDR_ANY);/*绑定本机IP,使用宏定义绑定*/
int open = 1;
// // 开启reuse
// if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &open, sizeof(open)) == -1) {
// return -1;
// }
// // 关闭nagle
// if (setsockopt(listenfd, IPPROTO_TCP, TCP_NODELAY, &open, sizeof(open)) == -1) {
// return -1;
// }
/**
* bind函数把一个本地协议地址赋予一个套接字,对于网际协议,协议地址就是IP加端口的组合
* int bind(int sockfd, const struct sockaddr * myaddr, socklen_t addrlen)
* sockfd 初始化的套接字
* myaddr 协议地址
* addrlen 协议地址长度
* 若成功返回0 出错返回-1
*/
if(bind(listenfd ,(struct sockaddr*)&svraddr,sizeof(svraddr)) < 0){
printf("bind error \n");
return -1;
}
printf("bind success \n");
/**
* int listen(int sockfd, int backlog)
* sockfd当使用socket函数创建一个套接字时,它被假设为一个主动套接字,也就是说,它是一个将发送connect发起连接的客户端套接字。
* 当调用listen函数之后,它被转成一个被动套接字,只是内核应该接受连接请求。所以,调用listen之后套接字由CLOSED状态转到LISTEN状态;
*backlog 这个函数规定内核应该为相应套接字排队的最大连接数
* (1)未完成连接队列,在客户端发送一个SYN直到三次握手完成,都是这个状态,SYN_RCVD状态
* (2)已完成连接队列,这个表示三次握手完成的状态,ESTABLISHED状态
* 失败时返回-1
*/
if(listen(listenfd, 20) < 0){
printf("listen error \n");
return -1;
}
/**
* int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
* sockdf 服务器套接字莫描述符
* cliaddr 已连接的客户端协议地址
* addrlen 已连接的客户端协议地址长度
* 成功返回非负描述符,出错返回-1
*/
struct sockaddr_in cliaddr; /*只是声明,并没有赋值*/
memset(&cliaddr, 0, sizeof(cliaddr));
socklen_t ret = sizeof(cliaddr);
int sockfd= accept(listenfd, (struct sockaddr*)&cliaddr, &ret );
if(sockfd < 0){
printf("appect error \n");
return -1;
}
printf("appect success \n");
/**
* 这些函数直接在存储器和文件之间传送数据,没有应用级缓冲。对将二进制数据读写到网络和从网络读写二进制数据尤其有用
* ssize_t rio_readn(int fd, void *usrbuf, size_t n)
* ssize_t read(int fd,void*buf,size_t count)
* fd: 是文件描述符, 从command line获取数据时,为0
* buf: 为读出数据的缓冲区;
* count: 为每次读取的字节数(是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移)
*/
//处理接收到的字符;
// char *p;
// p = (char*)malloc(MAXLEN*(sizeof(char*))); //申请一块内存,存放读取数据
// memset(p,0,1);
// ret = read(0,p,MAXLEN);
char str[] = "HTTP/1.1 200 OK\r\nContent-Length:11\r\n\r\n hello world";
/** sockfd socket文件描述符
* buf 文件内容
* count 内容长度
* ssize_t write(int sockfd, const void * buff, size_t count);
**/
write(sockfd , str, sizeof(str));
close(sockfd );
close(listenfd);
}
服务器的实现
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...