1.创建套接字
#include <sys/socket.h>
int socket(int family, int type, int protocol);
/*
功能:
创建一个用于网络通信的socket套接字(描述符)
参数:
family:协议族(AF_INET、AF_INET6、PF_PACKET等)
type:套接字类(SOCK_STREAM、SOCK_DGRAM、SOCK_RAW等)
protocol:协议类别(0、IPPROATO_TCP、IPPROTO_UDP等)
返回值:
套接字
特点:
创建套接字时,系统不会分配端口
创建的套接字默认属性是主动的,及主动发起服务的请求;当作为服务器时,往往需要修改为被动的。
*/
//创建套接字demo
int sockfd=0;
sockfd=socket(AF_INET, SOCK_DGRAM,0);
if(sockfd<0)
{
perror("socket");
exit(-1);
}
/*
AF_INET: IPV4协议
SOCK_DGRAM:数据包套接字
0:选择所给定的family和type组合的系统默认值
*/
2.UDP编程-发送、绑定、接受数据
2.1 IPV4套接字地址结构
#include <netinet/in.h>
struct in_addr
{
in-addr_t s_addr;//4字节
};
stuct sockaddr_in
{
sa_family_t sin_family;//2字节
in_port sin_port;//2字节
struct in_addr_sin_addr;//4字节
char sin_zero[8];//8字节
};
//为了使不同格式地址能被传入套接字函数,地址必须要强制转换成通用套接字地址结构
#include <netinet/in.h>
struct sockaddr
{
sa_family_t sa_family;//2字节
char sa_data[14];//14字节
}
在定义源地址和目的地址结构的时候,选用struct sockaddr_in
例:
struct sockaddr_in my_addr;
当调用编程接口函数,且函数需要传入地址结构时需要用struct sockaddr进行强制转换
例:
bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
2.2 发送数据----sendto函数浅析
ssize_t sendto(int sockfd, const void *buf,
size_t nbytes,int flags,
const struct sockaddr *to,
socklen_t addrlen);
/*
功能:
向to结构体指针中指定的ip,发送UDP数据
参数:
sockfd:套接字
buf: 发送数据缓冲区
nbytes:发送数据缓冲区的大小
flags:一般为0
to:指向目的主机地址结构体的指针
addrlen:to所指向内容的长度
注意:
通过to和addrlen确定目的地址
可以发送0长度的UDP数据包
返回值:
成功:发送数据的字符数
失败:-1
*/
2.3 通过网络调试助手发送消息
通过Ubuntu终端向调试助手发送信息
参考例程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
unsigned short port=8088;
char *server_ip ="填写你自己电脑的IP地址";
if (argc>1)//通过main函数传参,传入ip地址
{
server_ip=argv[1];
}
if (argc>2)//通过main函数传参 传入端口号
{
port=atoi(argv[2]);
}
//创建UDP套接字
int sockfd;
sockfd=socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd<0)
{
perror("socket");
exit(-1);
}
//填充目的server socket地址
struct sockaddr_in dest_addr;
bzero(&dest_addr, sizeof(dest_addr));
dest_addr.sin_family=AF_INET;//目的套接字地址的协议家族赋值
dest_addr.sin_port=htons(port);//目的套接字地址的端口号赋值
inet_pton(AF_INET, server_ip, &dest_addr.sin_addr);//目的套接字地址的ip地址赋值
printf("发送数据到UDP服务器 %s:%d!\n", server_ip,port);
//发送数据到目的server
while(1)
{
char send_buf[512];
fgets(send_buf, sizeof(send_buf), stdin);
send_buf[strlen(send_buf)-1]='\0';//字符串最后一个'\n'变成'\0'
sendto(sockfd, send_buf,strlen(send_buf), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
}
close(sockfd);
return 0;
}