基于UDP协议的C/S模型
-
函数
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
- 功能::UDP协议专业的数据接收函数
- sockfd: 套接字描述符
- buf: 数据存储位置
- len: 最大接受字节数
- flags: 0阻塞,1不阻塞
- src_addr: 获取发送者地址
- addrlen: 设置结构体的字节数
- 返回值: 成功接收数据的字节数
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
- 功能 :UDP协议专业的数据发送函数
- sockfd: 套接字描述符
- buf: 待发送的缓存区首地址
- len: 待发送的数据字节数
- flags: 0阻塞,1不阻塞
- dest_addr: 目标计算机地址
- addrlen: 地址结构体的字节数
- 返回值: 成功发送数据的字节数
-
编程模型
Server Client 创建套接字(socket) 创建套接字 准备地址(本机地址sockaddr_in) 准备地址(目标机地址) 绑定(bind(sockfd+addr)) . . . . . . 接受请求(recvfrom) 发送请求(sendto) 响应请求(senfto) 接收响应(recvfrom) 关闭套接字 关闭套接字 - 注意:从服务器到客户端返回的路线是UDP协议自己设计的
-
例子
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> typedef struct sockaddr* SP; int main() { printf("服务器创建socketn\n"); int sockfd = socket(AF_INET,SOCK_DGRAM,0); if(sockfd < 0) { perror("socket"); return -1; } //准备地址 struct sockaddr_in addr = {}; addr.sin_family = AF_INET; addr.sin_port = htons(6655); addr.sin_addr.s_addr = inet_addr("地址"); socklen_t len = sizeof(addr); //绑定socket与地址 if(bind(sockfd,(SP)&addr,len)) { perror("bind"); return; } struct sockaddr_in addrcli = {}; char buf[1024] = {}; while(1) { //接受请求 int ret = recvfrom(sockfd,buf,sizeof(buf),0,(SP)&addrcli,&len); printf("recv:%s,ip:%s,port:%hu,size:%d\n",buf,inet_ntoa(addrcli.sin_addr),ntosh(addrcli.sin_port),ret); //响应请求 if(0 == strcmp("quit",buf)) { printf("see you agian\n"); break; } sendto(sockfd,buf,strlen(buf)+1,0,(SP)&addrcli,len); } //关闭套接字 close(sockfd); }
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> typedef struct sockaddr* SP; int main() { printf("服务器创建socketn\n"); int sockfd = socket(AF_INET,SOCK_DGRAM,0); if(sockfd < 0) { perror("socket"); return -1; } //准备地址 struct sockaddr_in addr = {}; addr.sin_family = AF_INET; addr.sin_port = htons(6677); addr.sin_addr.s_addr = inet_addr("47.97.229.46"); socklen_t len = sizeof(addr); struct sockaddr_in addrser = {}; while(1) { char buf[1024] = {}; printf(">"); //接受请求 gets(buf); sendto(sockfd,buf,strlen(buf)+1,0,(SP)&addr,len); if(0 == strcmp("quit",buf)) { printf("see you agian\n"); break; } //int ret = recvfrom(sockfd,buf,sizeof(buf),0,(SP)&addrser,&len); // printf("recv:%s,ip:%s,port:%hu,size:%d\n",buf,inet_ntoa(addrser.sin_addr),addrser.sin_port,ret); //响应请求 } //关闭套接字 close(sockfd); }
windows下的网络的编程
-
一般的软件都是Linux或Unix的系统的,而Windows系统作为客户端,windows下的socket编程的接口与Linux的基本一致,函数都声明再winsock2.h下
-
int WSAStartuo(WORD,LPWSADATA);
- 初始化网络库
- WORD:设置网络库的版本
- MAKEWORD(1,2): 第一位为主版本号,第二位是副版本号
- LPWSADATA:WSADATA数据结构的指针
-
SOCKET socket(int domain,int type,)
-
closesocket(sockfd)
- 关闭socket
-
int WSACLeanup(void)
- 卸载网络库
- 编译时添加 -lws2_32
-