服務器端:
1.獲取套接字
int fd;fd=socket(AF_INET,SOCK_DGRAM,0);if(fd<0){perror("socket");exit(0);}
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
-domain: 指定通信域(通信地址族);
-type: 指定套接字類型;? ??數據報套接字:SOCK_DGRAM
-protocol: 指定協議;? ? ?數據報接字唯一對應TCP,所以無需要指定協議,設為0即可
2.綁定套接字
struct sockaddr_in addr;bzero(&addr,sizeof(addr));addr.sin_port=htons(atoi(argv[2]));//man inet_aton,判斷地址轉換是否成功if((inet_aton(argv[1],&addr.sin_addr))==0){fprintf(stderr,"Invalid address\n");//表示將“Invalid address”給標準錯誤stderrexit(0);}if(bind(fd,(struct sockaddr *)&addr,sizeof(addr))<0){perror("bind");exit(0);}
函數1:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
-sockfd:socket函數生成的套接字
-addr:通信結構體
-addrlen:通信結構體的長度
注意:參數addr是通用結構體sockaddr,要將初始化的sock_in結構體強制轉換
struct sockaddr_in { sa_family_t ? ?sin_family;
/* 地址族: AF_INET */ in_port_t ? ? ?sin_port; ?
/* 網絡字節序的端口號 */ struct in_addr sin_addr; ?
/*IP地址結構體 */ };
/* IP地址結構體 */ struct in_addr { uint32_t ? ? ? s_addr; ? ? /* 網絡字節序的IP地址 */ };
函數2:
在C語言中,inet_aton函數用于將表示IPv4地址的字符串轉換為網絡字節序的32位二進制數。該函數的原型如下:
int inet_aton(const char *cp, struct in_addr *inp);
其中:
- cp是一個指向表示IPv4地址的字符串的指針。
- inp是一個指向in_addr結構的指針,用于存儲轉換后的IPv4地址。
函數返回值為整型,如果字符串成功轉換為IPv4地址,則返回1;如果轉換失敗,則返回0。
函數3:
`bzero()` 函數用于將指定長度的內存區域清零,即將所有字節初始化為0。它通常用于清空敏感的數據或準備數據結構。`bzero()` 函數在許多系統中已經被廢棄,應該使用更現代的函數`memset()` 來替代。其原型如下:
void bzero(void *s, size_t n);
其中,參數 `s` 是指向要清零的內存區域的指針,參數 `n` 是要清零的字節數。
3.接收數據
while(1){bzero(buf,BUFSIZ);recvfrom(fd,buf,BUFSIZ,0,NULL,NULL);printf("buf=%s\n",buf);}close(fd);
函數原型:ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
? ? ? ? ? ? ? ? ? ? ? ? ? struct sockaddr *src_addr, socklen_t *addrlen);
功能:接收數據,并將接收到的數據存放到buf指向的緩沖區中。
參數說明:
- sockfd:要接收數據的套接字文件描述符。
- buf:指向用于存放接收數據的緩沖區。
- len:緩沖區的長度。
- flags:一些控制接收操作的標志。
- src_addr:指向發送方的地址結構體的指針。
- addrlen:發送方地址結構體的長度。
返回值:成功接收到數據時,返回接收到的數據的長度;失敗時,返回-1并設置errno。
原始代碼
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<strings.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
int main(int argc ,char *argv[]){int fd;char buf[BUFSIZ]={};struct sockaddr_in addr;if(argc<3){fprintf(stderr,"%s<addr><port>\n",argv[0]);exit(0);}fd=socket(AF_INET,SOCK_DGRAM,0);if(fd<0){perror("socket");exit(0);}bzero(&addr,sizeof(addr));addr.sin_port=htons(atoi(argv[2]));//man inet_aton,判斷地址轉換是否成功if((inet_aton(argv[1],&addr.sin_addr))==0){fprintf(stderr,"Invalid address\n");//表示將“Invalid address”給標準錯誤stderrexit(0);}if(bind(fd,(struct sockaddr *)&addr,sizeof(addr))<0){perror("bind");exit(0);}while(1){bzero(buf,BUFSIZ);recvfrom(fd,buf,BUFSIZ,0,NULL,NULL);printf("buf=%s\n",buf);}close(fd);return 0;
}
客戶端:
1.獲取套接字
int fd;fd=socket(AF_INET,SOCK_DGRAM,0);if(fd<0){perror("socket");exit(0);}
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
-domain: 指定通信域(通信地址族);
-type: 指定套接字類型;? ??數據報套接字:SOCK_DGRAM
-protocol: 指定協議;? ? ?數據報接字唯一對應TCP,所以無需要指定協議,設為0即可
2.發送數據
char buf[BUFSIZ]={};struct sockaddr_in addr;socklen_t addrlen;addrlen=sizeof(addr);bzero(&addr,sizeof(addr));addr.sin_port=htons(atoi(argv[2]));//man inet_aton,判斷地址轉換是否成功if((inet_aton(argv[1],&addr.sin_addr))==0){fprintf(stderr,"Invalid address\n");//表示將“Invalid address”給標準錯誤stderrexit(0);}while(1){bzero(buf,BUFSIZ);printf("input>");fgets(buf,BUFSIZ,stdin);sendto(fd,buf,strlen(buf),0,(struct sockaddr *)&addr,addrlen);}
函數1:
在C語言中,inet_aton函數用于將表示IPv4地址的字符串轉換為網絡字節序的32位二進制數。該函數的原型如下:
int inet_aton(const char *cp, struct in_addr *inp);
其中:
- cp是一個指向表示IPv4地址的字符串的指針。
- inp是一個指向in_addr結構的指針,用于存儲轉換后的IPv4地址。
函數返回值為整型,如果字符串成功轉換為IPv4地址,則返回1;如果轉換失敗,則返回0。
函數2:
`bzero()` 函數用于將指定長度的內存區域清零,即將所有字節初始化為0。它通常用于清空敏感的數據或準備數據結構。`bzero()` 函數在許多系統中已經被廢棄,應該使用更現代的函數`memset()` 來替代。其原型如下:
void bzero(void *s, size_t n);
其中,參數 `s` 是指向要清零的內存區域的指針,參數 `n` 是要清零的字節數。
函數3:
sendto函數用于向指定的套接字發送數據。其聲明如下:
```c
#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
```
參數解釋:
- `sockfd`: 要發送數據的套接字文件描述符。
- `buf`: 指向要發送的數據的指針。
- `len`: 要發送的數據的長度。
- `flags`: 指定發送數據時的標志,通常為0。
- `dest_addr`: 目標地址的結構體指針,其中包含目標主機的IP地址和端口號。
- `addrlen`: 目標地址結構體的長度。
成功發送數據時,sendto函數返回發送的字節數。如果發生錯誤,則返回-1,并設置errno變量指示錯誤原因。
?
注意:
1.nc -u +IP地址+端口號,連接服務器,本地回環
2.udp停止服務器端,再開啟后,客戶端也是可以正常發送,服務器端正常接收
原始代碼:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<strings.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>
int main(int argc ,char *argv[]){int fd;char buf[BUFSIZ]={};struct sockaddr_in addr;socklen_t addrlen;addrlen=sizeof(addr);if(argc<3){fprintf(stderr,"%s<addr><port>\n",argv[0]);exit(0);}fd=socket(AF_INET,SOCK_DGRAM,0);if(fd<0){perror("socket");exit(0);}bzero(&addr,sizeof(addr));addr.sin_port=htons(atoi(argv[2]));//man inet_aton,判斷地址轉換是否成功if((inet_aton(argv[1],&addr.sin_addr))==0){fprintf(stderr,"Invalid address\n");//表示將“Invalid address”給標準錯誤stderrexit(0);}while(1){bzero(buf,BUFSIZ);printf("input>");fgets(buf,BUFSIZ,stdin);sendto(fd,buf,strlen(buf),0,(struct sockaddr *)&addr,addrlen);}close(fd);return 0;
}