1. socket
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
功能:创建一个套接字,返回一个文件描述符
参数:
domain:通信域
AF_UNIX 本地通信
AF_INET IPV4网络通信
AF_PACKET 底层通信
type:socket的类型
SOCK_STREAM 流式套接字 tcp
SOCK_DGRAM 数据报套接字 UDP
SOCK_RAW 底层通信
protocol:协议,一般为0
返回值:
成功:文件描述符
失败:-1
例子:
int sockfd;
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("fail to socket");
//return -1;
exit(1);
}
2. bind
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:将套接字与网络信息结构体绑定
参数:
sockfd:文件描述符,socket的返回值
addr:网络信息结构体
通用的(一般不用):
struct sockaddr {
sa_family_t sa_family; 2个字节
char sa_data[14]; 14个字节
}
一般使用:sockaddr_in
#include <netinet/in.h>
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_); 协议族 AF_INET 2字节
in_port_t sin_port; 端口号 2个字节
struct in_addr sin_addr; IP地址 4个字节
这个没有用,为了保证与sockaddr大小一致
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
addrlen:addr的大小
返回值:
成功:0
失败:-1
例子:
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9999);
serveraddr.sin_addr.s_addr = inet_addr("192.168.1.23");
if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr_in)) < 0)
{
perror("fail to bind");
exit(1);
}
3. listen
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
功能:将套接字设置为监听模式
参数:
sockfd:文件描述符,socket的返回值
backlog:允许同时响应连接的客户端的个数
一般设置为5 10
返回值:
成功:0
失败:-1
例子:
if(listen(sockfd, 5) < 0)
{
perror("fail to listen");
exit(1);
}
4. accept
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:阻塞等待客户端的连接请求
参数:
sockfd:文件描述符,socket的返回值
addr:网络信息结构体(自动填充的客户端的网络信息结构体)
addrlen:addr的大小
返回值:
成功:返回新的文件描述符(此文件描述符用于通信)
失败:-1
例子:
int acceptfd;
struct sockaddr_in clientaddr;
socklen_t addlen = sizeof(clientaddr);
if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addlen)) < 0)
{
perror("fail to accept");
exit(1);
}
5. connect
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:发送客户端的连接请求
参数:
sockfd:文件描述符,socket的返回值
addr:服务器网络信息结构体
addrlen:addr的大小
返回值:
成功:0
失败:-1
6. send
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:发送数据
参数:
sockfd:文件描述符
服务器端:accept的返回值
客户端:socket的返回值
buf:发送的数据
len:buf 的长度
flags:标志位
0 阻塞
MSG_DONTWAIT 非阻塞
返回值:
成功:发送的数据的长度
失败:-1
7. recv
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:接收数据
参数:
sockfd:文件描述符
服务器端:accept的返回值
客户端:socket的返回值
buf:接收的数据
len:buf 的长度
flags:标志位
0 阻塞
MSG_DONTWAIT 非阻塞
返回值:
成功:接收的数据的长度
0:表示对方异常退出时,此时recv返回0
失败:-1
TCP网络编程
#include <stdio.h> //printf
#include <arpa/inet.h> //inet_addr htons
#include <sys/types.h>
#include <sys/socket.h> //scoket bind listen accept connect
#include <netinet/in.h> //sockaddr_in
#include <stdlib.h> //exit
#include <unistd.h> //close
#include <string.h>
#define N 128
#define errlog(errmsg) do{perror(errmsg);\
printf("%s-->%s-->%d\n", __FILE__, __func__, __LINE__);\
exit(1);\
}while(0)
服务器端
int main(int argc, const char *argv[])
{
int sockfd, acceptfd;
struct sockaddr_in serveraddr, clientaddr;
socklen_t addrlen = sizeof(serveraddr);
char buf[N] = {};
if(argc < 3)
{
printf("the argument is too less\n");
exit(1);
}
//第一步:创建套接字
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
errlog("fail to socket");
}
//第二步:填充服务器网络信息结构体
//inet_addr:将点分十进制IP地址转化为网络字节序的整型数据
//htons:将主机字节序转化为网络字节序
//atoi:将数字型字符串转化为整型数据
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//第三步:将套接字域网络信息结构体绑定
if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
errlog("fail to bind");
}
//第四步:将套接字设置为监听状态
if(listen(sockfd, 5) < 0)
{
errlog("fail to listen");
}
//第五步:阻塞等待客户端的连接请求
if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)) < 0)
{
errlog("fail to accept");
}
//接收数据,并打印
recv(acceptfd, buf, N, 0);
printf("buf : %s\n", buf);
close(acceptfd);
close(sockfd);
return 0;
}
客户端
int main(int argc, const char *argv[])
{
int sockfd;
struct sockaddr_in serveraddr;
socklen_t addrlen = sizeof(serveraddr);
char buf[N] = {};
if(argc < 3)
{
printf("the argument is too less\n");
exit(1);
}
//第一步:创建套接字
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
errlog("fail to socket");
}
//第二步:填充服务器网络信息结构体
//inet_addr:将点分十进制IP地址转化为网络字节序的整型数据
//htons:将主机字节序转化为网络字节序
//atoi:将数字型字符串转化为整型数据
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//第三步:向服务器端发送连接请求
if(connect(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0)
{
errlog("fail to connect");
}
//从终端输入,发送数据
fgets(buf, N, stdin);
buf[strlen(buf) - 1] = '\0';
if(send(sockfd, buf, N, 0) < 0)
{
errlog("fail to send");
}
close(sockfd);
return 0;
}