关于P2P通讯原理与实现你们能够参见参见P2P通讯原理与实现(C语言)文档,我这里就不在详述了。windows
咱们先定义一下信息的结构体,用于发送和接受信息:socket
/// <summary>信息结构的指针型</summary> typedef struct _message *lp_message; /// <summary>信息结构</summary> typedef struct _message { union { struct { char buff[1030]; }; struct { char cmd[6]; char rt_code[32]; char data[992]; }; }; SOCKADDR_IN addr; };
在这个结构体中,我采用了一个union同时定义了两种读取数据和写入数据的格式,一种是整个数据buffer的,另外一种是将buffer分为cmd、rt_code和data三部分的。其中cmd为固定6个大写字母的通信命令,rt_code为32字节的运行码,data是命令执行的数据内容。函数
因为在通信过程当中,这个信息结构体会常常被用到,所以须要定义一个初始化结构指针的函数。.net
/// <summary>创建一个服务信息</summary> lp_message newMessage() { lp_message msg = (lp_message)malloc(sizeof(_message)); memset(msg->buff, 0, sizeof(_message)); return msg; }
关于Socket的链接与侦听,p2pserver函数是UDP通信的核心函数,在这个函数开始咱们首先创建UDP的通信,打开端口,绑定服务,最后启动侦听循环,不断地接收客户端发送过来的信息,一旦收到有效信息,就将信息交由receivedMessage函数来进行处理。指针
/// <summary>p2p服务</summary> void p2pserver(u_short port, char* connstr) { WSADATA msaData; if (WSAStartup(MAKEWORD(2, 2), &msaData) != 0) ErrorHandle("WSAStartup error!"); hServer = socket(AF_INET, SOCK_DGRAM, 0); SOCKADDR_IN addrServ; addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrServ.sin_family = AF_INET; addrServ.sin_port = htons(port); bind(hServer, (SOCKADDR*)&addrServ, sizeof(SOCKADDR)); lp_message msg = newMessage(); int addr_len = sizeof(SOCKADDR_IN); while (true) { int len = recvfrom(hServer, &msg->buff[0], buff_size, 0, (SOCKADDR*)&msg->addr, &addr_len); if (len > 6) { HANDLE h = (HANDLE)_beginthreadex(NULL, 0, &receivedMessage, msg, 0, NULL); msg = newMessage(); } } closesocket(hServer); WSACleanup(); }
处理相应函数为receivedMessage,这个函数咱们将在后面根据业务进行不断的扩展来使用。code
/// <summary>处理接收到的信息</summary> unsigned WINAPI receivedMessage(void *arg) { lp_message msg = (lp_message)arg; printf("Received a [%s] from client %s, string is: %s\n", msg->cmd, inet_ntoa(msg->from->sin_addr), msg->buf); //do anything free(msg); return 0; }
最后看看主函数的简单写法,若是想以windows服务的方式进行,能够参照windows服务的方式进行改造。server
int main() { HANDLE hMutex = CreateMutex(NULL, false, (LPCWSTR)"James"); p2pserver(9000, ""); CloseHandle(hMutex); return 0; }