socket(PF_INET,SOCK_STREAM,0) 或socket(AF_INET,SOCK_STREAM,0)
socket()系统调用,带有三个参数:
1、参数domain指明通信域,如PF_UNIX(unix域),PF_INET(IPv4),PF_INET6(IPv6)等2、type指明通信类型,最常用的如SOCK_STREAM(面向连接可靠方式, 比如TCP)、SOCK_DGRAM(非面向连接的非可靠方式,比如UDP)等。 SOCK_STREAM 是数据流,一般是tcp/ip协议的编程,SOCK_DGRAM分是数据抱,是udp协议网络编程。3、参数protocol指定需要使用的协议。虽然可以对同一个协议 家族(protocolfamily)(或者说通信域(domain))指定不同的协议 参数,但是通常只有一个。对于TCP参数可指定为IPPROTO_TCP,对于 UDP可以用IPPROTO_UDP。你不必显式制定这个参数,使用0则根据前两个参数使用默认的协议。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <main.h>
// c即是tcp_cli s即是tcp_srv
void net_send(struct tcp_cli * tc, void *buf, int len)
{
struct tcp_cli *c = (struct tcp_cli*)tc;
struct tcp_srv *s = c->srv;
epoll_del_event(s->epfd, c->ev_rx);//停止接收,避免干扰
c->buf = buf;//c即是tcp_cli
c->len = len;
epoll_add_event(s->epfd, c->ev_tx);//开启发送
}
static void rx_app_handler(int sock, void *arg)
{
struct tcp_cli *c = arg; //arg从c即client那儿来,因为在创建事件时把client作为arg参数保存进去了
int res = 0;
unsigned char *pbuf;//数据保存到pbuf
pbuf = &c->req[0];
res = read(c->sock, pbuf, FRAME_HDR_SZ);
process_incoming(c);
}
static void tx_app_handler(int sock, void *arg)
{
struct tcp_cli *c = arg;
struct tcp_srv *s = c->srv;
int res = 0;
res = send(sock, c->buf, c->len, 0);//发送数据
if (res > 0) {
c->len -= res;
if (c->len == 0) {
epoll_del_event(s->epfd, c->ev_tx);//停止发送
epoll_add_event(s->epfd, c->ev_rx);//开启接收
}
}
}
int build_ack(unsigned char *rsp, unsigned char type, unsigned char id,
unsigned char len, unsigned char *data)
{
rsp[LEN_POS] = len;
rsp[CMD0_POS] = type;
rsp[CMD1_POS] = id;
memcpy(&rsp[DAT_POS], data, len);
//由data所指内存区域复制len个字节到&rsp[DAT_POS]所指内存区域。
return len + FRAME_HDR_SZ;
}
int net_sys_init( )
{
struct sockaddr_in addr;
struct sockaddr_in sin;
struct tcp_cli *c;
int new_sock;
int len;
struct tcp_srv *s = calloc(1, sizeof(struct tcp_srv));
s->epfd = srv_main->epfd;
s->sock = socket(AF_INET, SOCK_STREAM, 0);
//通信域 tcp/ip协议的编程 协议
//ipv4 数据流 0为默认
addr.sin_addr.s_addr = INADDR_ANY;
//可以使用任何ip地址通信
addr.sin_family = AF_INET;//ipv4协议
addr.sin_port = htons (DEF_TCP_SRV_PORT);//自定义端口 #define DEF_TCP_SRV_PORT 19868
bind(s->sock, (struct sockaddr*)&addr, sizeof(struct sockaddr));//将sock和地址绑定起来
listen(s->sock, 5); //连接数是5
new_sock = accept(s->sock, (struct sockaddr*)&sin, &len);//等待客户端连接
//保存客户端的fd 连接上来的客户端的地址
c = calloc(1, sizeof(struct tcp_cli));
c->sock = new_sock; //保存客户端的fd
memcpy(&c->addr, &sin, len);//将客户端的ip地址拷贝到sin中
c->srv = s;
// c->req_total = FRAME_HDR_SZ;
c->ev_rx = epoll_event_create(c->sock,EPOLLIN,rx_app_handler, c);//把client即是c作为arg参数保存进去
c->ev_tx = epoll_event_create(c->sock,EPOLLOUT,tx_app_handler, c);
epoll_add_event(c->srv->epfd, c->ev_rx);
//return s;
srv_main->srv = s;
return 0;
}