1.写network.h
#pragma once
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdbool.h>
typedef struct NetWork
{
int type; //通信协议类型
int sock_fd; //socket描述符
struct sockaddr_in addr;//通信地址
socklen_t addrlen;//通信地址字节数
bool issvr;//是否是服务器
}NetWork;
typedef struct sockaddr *SP;
//分配内存,创建socket套接字,初始化地址,绑定,监听,连接
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);
//关闭socket对象并释放内存
void close_nw(NetWork *nw);
//获取IP地址
const char *getip_nw(NetWork *nw);
2.写network.c
#include "network.h"
//分配内存,创建socket套接字,初始化地址,绑定,监听,连接
NetWork *init_nw(int type,short port,const char *ip,bool issvr)
{
NetWork *nw=malloc(sizeof(NetWork));
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->type=type;
nw->issvr=issvr;
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))
{
free(nw);
perror("bind");
return NULL;
}
//TCP服务器端需要监听
if (SOCK_STREAM==type&&listen(nw->sock_fd,50))
{
free(nw);
perror("listen");
return NULL;
}
}
else if (SOCK_STREAM==type)//TCP客户端
{
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协议且为服务器端的NetWork对象才能调用此函数");
return NULL;
}
//为新的NetWork分配内存并初始化
NetWork *nw=malloc(sizeof(NetWork));
nw->addrlen=svr_nw->addrlen;
nw->type=SOCK_STREAM;
nw->issvr=true;
nw->sock_fd=accept(svr_nw->sock_fd,(SP)&nw->addr,&nw->addrlen);
if (nw->sock_fd<0)
{
free(nw);
perror("accept");
return NULL;
}
return 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);
}
}
//关闭socket对象并释放内存
void close_nw(NetWork *nw)
{
close(nw->sock_fd);
free(nw);
}
//获取IP地址
const char *getip_nw(NetWork *nw)
{
return inet_ntoa(nw->addr.sin_addr);
}
3.工具已经封装好了,下面进行使用
写服务器端代码
#include "network.h"
void server(NetWork *fd)
{
char buf[4096];
size_t buf_size=sizeof(buf);
while(1)
{
int ret=recv_nw(fd,buf,buf_size);
if(ret<=0||0==strcmp("quit",buf))
{
printf("客户端%d退出\n",fd->sock_fd);
break;
}
printf("from %d recv:%s bits:%d\n",fd->sock_fd,buf,ret);
strcat(buf,":return");
ret=send_nw(fd,buf,strlen(buf)+1);
}
close_nw(fd);
exit(0);
}
int main(int argc,const char* argv[])
{
NetWork *nw=init_nw(SOCK_STREAM,atoi(argv[2]),argv[1],true);
while(1)
{
NetWork *fd=accept_nw(nw);
if(0==fork()) server(fd);
}
return 0;
}
写客户端代码
#include "network.h"
int main(int argc,const char* argv[])
{
NetWork *nw=init_nw(SOCK_STREAM,atoi(argv[2]),argv[1],false);
char buf[4096];
size_t buf_size=sizeof(buf);
while(1)
{
printf(">>>>>");
scanf("%s",buf);
int ret=send_nw(nw,buf,strlen(buf)+1);
if(ret<=0||0==strcmp("quit",buf))
{
printf("通信结束!\n");
close_nw(nw);
break;
}
ret=recv_nw(nw,buf,buf_size);
if(ret<=0)
{
close_nw(nw);
break;
}
printf("from %d recv:%s bits:%d\n",nw->sock_fd,buf,ret);
}
return 0;
}
4.
将代码部分完成后,对其进行封装
封装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