socket: 创建套接字
#include<sys/socket.h>
int socket(int family,int type,int protocal)
参数
family: AF_INET <IPv4协议>
AF_INET6 <IPv6协议>
AF_LOCAL <UNIX域协议>
AF_ROUTE <路由套接字>
AF_KEY <密钥套接字>
type: SOCK_STREAM <流式套接字,TCP>
SOCK_DGREAM <数据报套接字,UDP>
SOCK_RAM <原始套接字>
protocal: 原始套接字<TCP,UDP填0>
返回值
成功:非负套接字描述符
出错:-1
bind: 绑定IP和端口号
#include<sys/socket.h>
#include<sys/types.h>
int bind(int sockfd,struct sockaddr *addr,int addrlen)
参数
sockfd 套接字描述符
addr 绑定的地址,通用地址结构体
addlen 地址长度
返回
成功: 0
出错:-1
补充
struct sockaddr{
sa_family_t sa_family; //协议族
char sa_data[14]; //地址信息
};/**通用地址结构体定义**/
struct sockaddr_in{
sa_family_t sin_fanily; //协议族.一般写AF_INET
in_port_t sin_port; //端口号. htons(0),随机分配端口号
struct in_addr sin_addr;//IP地址. htonl(INADDR_ANY),0.0.0.0
};/**IPv4协议族地址格式,调用bin函数需要类型转换**/
struct in_addr{
uint32_t s_addr; //IP
};
connect: UDP中的connect没有连接的概念,但是可以指定通信对象。
#include<sys/socket.h>
int connect(int sockfd,struct sockaddr *serv_addr,int addrlen)
参数
sockfd 套接字描述符
serv_addr 服务器地址
addrlen 地址长度
send: 发送数据
#include<sys/socket.h>
int send(int sockfd,const void *buf,int len,int flags)
参数
sockfd 套接字描述符
buf 发送缓冲区首地址
len 发送数据长度
flags 一般为0
返回
成功:实际发送的字节数
失败:-1
recv: 接收数据
#include<sys/socket.h>
int recv(int sockfd,const void *buf,int len,int flags)
参数
sockfd 套接字描述符
buf 接收缓冲区首地址
len 接收数据长度
flags 一般为0
返回
成功:实际接收的字节数
失败:-1
sendto: 发送数据
#include<sys/socket.h>
int sendto(int sockfd,const void *buf,int len,int flags,const struct sockaddr* to,int tolen)
参数
sockfd 套接字描述符
buf 发送缓冲区首地址
len 发送数据的长度
flags: 一般为0
to: 接收方地址
tolen: 接收方地址长度
返回
成功:实际发送的数据长度
失败:-1
recvfrom: 接收数据
#include<sys/socket.h>
int recvfrom(int sockfd,const void *buf,int len,int flags,const struct sockaddr* from,int *fromlen)
参数
sockfd 套接字描述符
buf 发送缓冲区首地址
len 发送数据的长度
flags: 一般为0
to: 发送方地址
tolen: 发送方地址长度
返回
成功:实际发送的数据长度
失败:-1
UDP服务器示例
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, const char *argv[])
{
int sockfd;
struct sockaddr_in seraddr, cliaddr;
char buf[1024] = "\0";
int ret;
socklen_t addrlen = sizeof(cliaddr);
//step 1:打开套接字接口
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(-1 == sockfd)
{
perror("socket");
return -1;
}
//step 2:绑定
memset(&seraddr, 0, sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(8888);
seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));
if(-1 == ret)
{
perror("bind");
return -1;
}
//step 3:接受数据
ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&cliaddr, &addrlen);
if(-1 == ret)
{
perror("recvfrom");
return -1;
}
printf("recv from %s:%d, content is %s\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port), buf);
//step 4: 发送数据
ret = sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&cliaddr, addrlen);
if(-1 == ret)
{
perror("sento");
return -1;
}
printf("sendto successful!\n");
close(sockfd);
return 0;
}
客户端示例
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, const char *argv[])
{
int sockfd;
struct sockaddr_in seraddr;
char buf[1024] = "hello udp server";
int ret;
socklen_t addrlen = sizeof(seraddr);
//step 1:打开套接字接口
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(-1 == sockfd)
{
perror("socket");
return -1;
}
//step 2: 发送数据
memset(&seraddr, 0, sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(8888);
seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&seraddr, sizeof(seraddr));
if(-1 == ret)
{
perror("sento");
return -1;
}
printf("sendto successful!\n");
//step 3:接受数据
ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&seraddr, &addrlen);
if(-1 == ret)
{
perror("recvfrom");
return -1;
}
printf("recv from %s:%d, content is %s\n", inet_ntoa(seraddr.sin_addr), ntohs(seraddr.sin_port), buf);
close(sockfd);
return 0;
}