最开始是网上找到相关的客户端,和服务端 的程序,然后试着去理解,但是这个过程很难过,因为从来没有接触过的,但是没办法,只能硬着头皮啃,问老师,问学长,网上看视频。终于是吧他啃下来了。
服务端的代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BACKLOG 100
int main()
{
int iListenSock = socket(AF_INET, SOCK_STREAM, 0);
//int socket(int domain, int type, int protocol);socket函数对应于普通文件的打开操作。普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。
//1.协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
//2.type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等
//3.protocol故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议
sockaddr_in addr;//
memset(&addr, 0, sizeof(addr));
inet_aton("192.168.1.66", &addr.sin_addr);
//是一个改进的方法来将一个字符串IP地址转换为一个32位的网络序列IP地址。
/* struct sockaddr_in
{ unsigned short int sin_family;//协议族(family)连接方式
uint16_t sin_port;//定义端口号,可以直接指定,也可由系统指定,也是网络字节序,
一般用htons()函数转换。
struct in_addr sin_addr;//为ip地址,是二进制的网络字节序,
一般用inet_addr()函数完成转换
unsigned char sin_zero[8];//一般不使用
}
*/
addr.sin_family = AF_INET;//协议族(family)采用IPv4网络协议
addr.sin_port = htons(8888);//服务器监听端口号 8888
int iOpt = 1;
setsockopt(iListenSock, SOL_SOCKET, SO_REUSEADDR, &iOpt, sizeof(iOpt)); // 标配
bind(iListenSock, (sockaddr*)&addr, sizeof(addr));//bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。
listen(iListenSock, BACKLOG);//BACKLOG 100指定同时能够处理的最大连接要求
epoll_event ev;
ev.data.fd = iListenSock;
ev.events = EPOLLIN;
epoll_event events[BACKLOG + 1];
int epollFD = epoll_create(BACKLOG + 1); // 告诉内核监测的数目, 返回的epollFD为epoll管理句柄
epoll_ctl(epollFD, EPOLL_CTL_ADD, iListenSock, &ev); // 将ev和对应的iListenSock添加到epoll句柄,用于被epollFD管理
while(1)
{
int timeoutMS = -1; // 永不超时
int nfds = epoll_wait(epollFD, events, BACKLOG + 1, timeoutMS); // events和nfds是一对输出值
printf("nfds is %d\n", nfds);
for(int i = 0; i < nfds; i++)
{
if(events[i].data.fd == iListenSock) // 用于监听客户端连接的socket
{
int iConnSock = accept(iListenSock, NULL, NULL);
if (iConnSock < 0)
{
continue;
}
ev.data.fd = iConnSock;
ev.events = EPOLLIN;
epoll_ctl(epollFD, EPOLL_CTL_ADD, iConnSock, &ev); // 将ev和对应的iConnSock添加到epoll句柄,用于被epollFD管理
printf("new sock came, fd is %d\n", iConnSock);
}
else
{
int iConnSock = events[i].data.fd; // 用于通信的socket
char szBuf[1024] = {0};
int recvLen = recv(iConnSock, szBuf, sizeof(szBuf) - 1, 0);
if (recvLen > 0)
{
printf("recv data [%s] from fd [%d]\n", szBuf, iConnSock);
}
else if(0 == recvLen)
{
ev.data.fd = iConnSock;
epoll_ctl(epollFD, EPOLL_CTL_DEL, iConnSock, &ev);
close(iConnSock);
printf("connection closed, local fd is [%d]\n", iConnSock);
}
else
{
ev.data.fd = iConnSock;
epoll_ctl(epollFD, EPOLL_CTL_DEL, iConnSock, &ev);
close(iConnSock);
printf("recv error, local fd is [%d]\n", iConnSock);
}
}
}
}
close(epollFD);
close(iListenSock);
return 0;
}
虽然程序搞懂了,但是对于网络配置的,还是不懂,在其中遇到,PC,虚拟机,板子的网络Ping通
主要问题如下
这个是因为程序里面的IP地址不是你服务器的地址,导致虽然在虚拟机和板子网络可以ping得通,但是运行客户端的程序没有反应。解决方法,通过在虚拟机输入ifconfig 查看IP地址。
接下来可能会出现接来的问题;
你发现你的Ip地址好像没有,
这可能是你要去开启你的网卡设置。
按照步骤走,IP可以自己选择,也可以选择自动,但是还是自己输入比较好,因为要选择跟板子上通一个网段。
我通过交叉编译得到了板子上linux可执行程序,许多方便改变,这个也是一个大问题,我尝试了很久通过NFS但是就是设置不好服务端的文件。最后还是选择了用u盘挂载,