自制网络连接工具(支持tcp/udp,客户端/服务端)
将网络连接工具制作成共享库
network.h
#ifndef NETWORK_H
#define NETWORK_H
#include<netinet/in.h>
#include<sys/socket.h>
#include<stdbool.h>
typedef struct Network
{
int type;//网络类型,TCP或UDP
int sock_fd;//socket文件描述符
struct sockaddr_in addr;//地址结构体
socklen_t addrlen;//地址长度
bool issvr;//是否是服务端
}Network;
typedef struct sockaddr* SP;
//分配内存,创建套接字,初始化地址,绑定,监听,连接
Network* init_nw(int type,short port,const char* ip,bool issvr);
//等待连接,只有TCP的服务端才能调用
Network* accept_nw(Network* svr_nw);
//具备send和sendto的功能,可以发送数据
int send_nw(Network* nw,void* buf,size_t len);
//具备recv和recvfrom的功能,可以接收数据
int recv_nw(Network* nw,void* buf,size_t len);
//具备close的功能,并且释放资源
void close_nw(Network* nw);
//获取ip地址
char* get_ip(Network* nw);
#endif //NETWORK_H
对函数具体实现:
network.c
#include "network.h"
#include <stdio.h>
#include <stdlib.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
//分配内存,创建套接字,初始化地址,绑定,监听,连接
Network* init_nw(int type,short port,const char* ip,bool issvr)
{
Network* nw = (Network*)malloc(sizeof(Network));
if(nw == NULL)
{
return NULL;
}
nw->type=type;
nw->issvr=issvr;
nw->sock_fd=socket(AF_INET,type,0);
if(nw->sock_fd <0)
{
free(nw);
perror("socket");
return NULL;
}
//初始化地址结构体
bzero(&nw->addr,nw->addrlen);
//初始化地址
nw->addr.sin_family=AF_INET;
nw->addr.sin_port=htons(port);
nw->addr.sin_addr.s_addr=inet_addr(ip);
nw->addrlen=sizeof(struct sockaddr_in);
if(issvr)
{
//绑定地址
if(bind(nw->sock_fd,(SP)&nw->addr,nw->addrlen)<0)
{
free(nw);
perror("bind");
return NULL;
}
//TCP的服务端监听
if(nw->type==SOCK_STREAM && listen(nw->sock_fd,50))
{
free(nw);
perror("listen");
return NULL;
}
}
else if(SOCK_STREAM == nw->type)
{
if(connect(nw->sock_fd,(SP)&nw->addr,nw->addrlen))
{
free(nw);
perror("connect");
return NULL;
}
}
return nw;
}
//等待连接,只有TCP的服务端才能调用
Network* accept_nw(Network* svr_nw)
{
if(SOCK_STREAM != svr_nw->type||!(svr_nw->issvr))
{
printf("只有TCP协议的服务器端才能调用accept_nw\n");
return NULL;
}
//为新的Network分配内存
Network* clt_nw = (Network*)malloc(sizeof(Network));
if(clt_nw == NULL)
{
return NULL;
}
clt_nw->addrlen=svr_nw->addrlen;
clt_nw->type=svr_nw->type;
clt_nw->issvr=true;
clt_nw->sock_fd=accept(svr_nw->sock_fd,(SP)&clt_nw->addr,&clt_nw->addrlen);
if(clt_nw->sock_fd <0)
{
free(clt_nw);
perror("accept");
return NULL;
}
return clt_nw;
}
//具备send和sendto的功能,可以发送数据
int send_nw(Network* nw,void* buf,size_t len)
{
if(nw->type == SOCK_DGRAM)
{
return sendto(nw->sock_fd,buf,len,0,(SP)&nw->addr,nw->addrlen);
}
else
{
return send(nw->sock_fd,buf,len,0);
}
}
//具备recv和recvfrom的功能,可以接收数据
int recv_nw(Network* nw,void* buf,size_t len)
{
if(nw->type == SOCK_DGRAM)
{
return recvfrom(nw->sock_fd,buf,len,0,(SP)&nw->addr,&nw->addrlen);
}
else
{
return recv(nw->sock_fd,buf,len,0);
}
}
//具备close的功能,并且释放资源
void close_nw(Network* nw)
{
close(nw->sock_fd);
free(nw);
}
//获取ip地址
const char* get_ip(Network* nw)
{
return inet_ntoa(nw->addr.sin_addr);
}
将代码部分完成后,对其进行封装
封装TCP\UDP通用通信代码库:
1、gcc -fpic -c network.c
2、gcc -shared -fpic network.o -o libnetwork.so
3、sudo cp libnetwork.so /usr/lib
4、sudo cp network.h /usr/include/
使用 gcc code.c -lnetwork