UDP协议端格式
- 16位UDP长度, 表⽰整个数据报(UDP⾸部+UDP数据)的最⼤⻓度;
- 如果校验和出错, 就会直接丢弃;
UDP特点
UDP传输的过程类似于寄信.- ⽆连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接;
- 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给;
- 应⽤层返回任何错误信息;
- ⾯向数据报: 不能够灵活的控制读写数据的次数和数量;
编写简单的UDP服务器
其功能为可以接收客户端消息,并可以返回给客户端一条消息。
服务器
#include<stdio.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<string.h> #include<stdlib.h> #include<arpa/inet.h> #include<unistd.h> //./service 192.168.1.113 8888 int main(int argc,char* argv[]) { if(argc != 3) { printf("Usage:%s [ip] [port]\n"); return 1; } int sock = socket(AF_INET,SOCK_DGRAM,0); { if(sock < 0) { printf("sock error\n"); return 2; } } struct sockaddr_in local; local.sin_family = AF_INET; local.sin_addr.s_addr = inet_addr(argv[1]); //将一个点分十进制转换成一个长整数 local.sin_port = htons(atoi(argv[2])); //atoi把字符串转换成整型数 htons 大小端转换 if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0) { printf("bind error!\n"); return 3; } char buf[1024]; struct sockaddr_in client; while(1) { socklen_t len = sizeof(client); ssize_t s = recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&client,&len); if(s > 0) { buf[s] = 0; //printf("[client echo#] %s\n",buf); printf("[%s | %d]: %s\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port),buf); printf("[please enter#]"); } fflush(stdout); ssize_t _s = read(0,buf,sizeof(buf)-1); sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&client,sizeof(client)); printf("\n=====================================\n"); } }
客户端
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include <stdlib.h> #include <arpa/inet.h> #include <unistd.h> //./client 192.168.1.113 8888 int main(int argc,char* argv[]) { if(argc != 3) { printf("Usage:%s [ip] [port]\n",argv[0]); return 2; } int sock = socket(AF_INET,SOCK_DGRAM,0); if(sock < 0) { printf("socket error!\n"); return 1; } struct sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(atoi(argv[2])); server.sin_addr.s_addr = inet_addr(argv[1]); char buf[1024]; struct sockaddr_in peer; while(1) { socklen_t len = sizeof(peer); printf("[please enter#] "); fflush(stdout); ssize_t s = read(0,buf,sizeof(buf)-1); if(s > 0) { buf[s-1] = 0; sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&server,sizeof(server)); ssize_t _s = recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&peer,&len); if(_s > 0) { buf[_s] = 0; printf("[server echo#] %s\n",buf); printf("======================================\n"); } } } close(sock); return 0; }
makefile:
.PHONY:allall:service client
service:service.c
gcc -o $@ $^
client:client.c
gcc -o $@ $^ -static
.PHONY:clean
clean:
rm -f service client
运行演示:
未输入ip地址及端口号,列出提示:
服务器:
客户端:
可以发现,客户端和服务器之间可以实现信息交流。如果将客户端在A电脑启动,在同一局域网下的B电脑打开客户端,也可以实现交流。
如果需要将客户端传给其他电脑,则需要关闭防火墙,并用scp发送过去
关闭防火墙: sudo service iptables stop 远程拷贝: scp命令:scp client 192.168.1.112:/home
client是需要传递的文件名
192.168.1.112是目标IP地址,IP地址与:/home之间无空格