TCP网络程序设计
Posted 汪自强
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TCP网络程序设计相关的知识,希望对你有一定的参考价值。
11.7 创建套接字
11.7.1 函数名
socket
11.7.2 函数原形
int socket(int domain, int type, int protocol);
11.7.3 函数功能
用于创建套接字
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
11.7.5 返回值
成功:返回文件fd
失败:-1
11.7.6 参数说明
domain:通信域
AF_INET,AF_INET6,AF_UNIX
type: 套接字类型
SOCK_DGRAM,SOCK_RAW,SOCK_SEQPACKET
protocol :一般为0
11.7 绑定套接字
11.7.1 函数名
bind
11.7.2 函数原形
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
11.7.3 函数功能
用于绑定套接字
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
11.7.5 返回值
成功:0
失败:-1
11.7.6 参数说明
sockfd:绑定套接字的文件描述符
addr: 套接字地址指针,下面是通用的地址类型
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
常用的IPV4的地址类型如下:
struct sockaddr_in {
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;//一个整数表示IP地址
unsigned char sin_zero[8];}
struct in_addr {
unsigned long s_addr;
}
addrlen:地址长度
以上使用一个整数表示IP地址,但是人们一般是使用4个字符串来表示IP地址,使用下面两个函数就可以进行转换
- 网络字节序
1. Little endian:将低序字节存储在起始地址
2. Big endian:将高序字节存储在起始地址
而网络上传输的模式都是大端模式,所以就有主机字节序-》网络字节序-》本机字节序
11.7 监听套接字
11.7.1 函数名
listen
11.7.2 函数原形
int listen(int sockfd, int backlog);
11.7.3 函数功能
用于监听套接字
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
11.7.5 返回值
成功:0
失败:-1
11.7.6 参数说明
sockfd:绑定套接字的文件描述符
backlog:该进程所要入队的最大长度
11.7 等待连接
11.7.1 函数名
accept
11.7.2 函数原形
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
11.7.3 函数功能
用于等待客户机连接
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
11.7.5 返回值
成功:返回新的一个文件描述符
失败:-1
11.7.6 参数说明
sockfd:创建的套接字的文件描述符
addr:一个指向套接字地址的指针
addrlen:地址的长度
11.7 发送数据
11.7.1 函数名
accept
11.7.2 函数原形
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
11.7.3 函数功能
用于发送数据
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
11.7.5 返回值
成功:返回发送的字节数
失败:-1
11.7.6 参数说明
sockfd:创建的套接字的文件描述符
buf:待发送数据指针
len:数据长度
flags:标志,一般为0
11.7 接收数据
11.7.1 函数名
recv
11.7.2 函数原形
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
11.7.3 函数功能
用于接收数据
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
11.7.5 返回值
成功:接收消息的字节数
失败:-1
11.7.6 参数说明
sockfd:创建的套接字的文件描述符
buf:待发送数据指针
len:数据长度
flags:标志,一般为0
11.7 关闭结束连接
11.7.1 函数名
close
11.7.2 函数原形
int close(int fd);
11.7.3 函数功能
用于关闭连接
11.7.4 所属头文件
#include <unistd.h>
11.7.5 返回值
成功:0
失败:-1
11.7.6 参数说明
fd:被关闭套接字的文件描述符
- 客户机的函数
11.7 客户机连接服务器
11.7.1 函数名
connect
11.7.2 函数原形
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
11.7.3 函数功能
用于客户机连接服务器
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
11.7.5 返回值
成功:0
失败:-1
11.7.6 参数说明
sockfd:创建的套接字的文件描述符
addr:服务器的地址指针
addrlen:地址长度
- 程序调试
调试过程中服务器程序遇到core dump问题,使用GDB调试发现是
printf("server get connection from %s\\r\\n",inet_ntoa(client_addr.sin_addr));//将客户机地址转化成字符串,打印客户机地址
这句话引起了Segmentation on on vprintf.c的错误,
在网络上查询发现是要包含以下头文件
#include <arpa/inet.h>//使用inet_ntoa网络地址转换成字符串函数需包含的头文件
服务器程序
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <netinet/in.h>//使用struct sockaddr_in需包含的头文件 #include <arpa/inet.h>//使用inet_ntoa网络地址转换成字符串函数需包含的头文件 #include <string.h> #include <stdio.h> #define portnum 3333//自定义网络端口 int main() { int sockfd,new_fd;//定义文件描述符,新的客户机文件描述符 struct sockaddr_in server_addr;//主机地址属性 struct sockaddr_in client_addr;//客户机地址 char buffer[128];//接收数据缓存 int nbyte; int sin_size; //1.创建套接字 if((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1)//如果创建错误,就返回 { printf("create socket error\\r\\n"); exit(1); } //2.1 设置要绑定的地址 bzero(&server_addr,sizeof(struct sockaddr_in));//将地址结构体先清零 server_addr.sin_family = AF_INET; //网络域 server_addr.sin_port = htons(portnum);//将两个字节的端口转换成网络字节序 server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//将任意的IP地址赋予数据段 //2.2绑定地址 bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr)); //第二个参数一般先使用sockaddr_in(便于定义结构体成员变量),然后在强制转化,能够更方便 //3.监听端口 listen(sockfd,5);//最大连接数是5 while(1) { //4.等待连接 sin_size = sizeof(struct sockaddr); new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size);//等待连接,注意第三个参数必须是指针 printf("server get connection from %s\\r\\n",inet_ntoa(client_addr.sin_addr));//将客户机地址转化成字符串,打印客户机地址 //5.接收数据 nbyte = recv(new_fd,buffer,128,0); buffer[nbyte] = \'\\0\'; printf("server recv : %s\\r\\n",buffer);//打印接收的数据 //6.结束连接 close(new_fd); //break; } close(sockfd); }
客户机程序
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <netinet/in.h>i//定义了sockaddr_in结构 #include <string.h> #include <stdio.h> #define portnum 3333//自定义网络端口 int main() { int sockfd,new_fd;//定义文件描述符,新的客户机文件描述符 struct sockaddr_in server_addr;//主机地址属性 char buffer[128];//接收数据缓存 int nbyte; //1.创建套接字 if((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1)//如果创建错误,就返回 { printf("create socket error\\r\\n"); exit(1); } //2.1 设置要连接的服务器的地址 bzero(&server_addr,sizeof(struct sockaddr_in));//将地址结构体先清零 server_addr.sin_family = AF_INET; //网络域 server_addr.sin_port = htons(portnum);//将两个字节的端口转换成网络字节序 server_addr.sin_addr.s_addr = inet_addr("192.168.1.141");//服务器的地址 //2.2连接服务器 if((connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))) == -1) { printf("connect error\\r\\n"); exit(1); } //3.发送数据到服务器 printf("Please input char sent to server\\r\\n"); fgets(buffer,128,stdin); send(sockfd,buffer,strlen(buffer),0); //4.关闭连接 close(sockfd); return 0; }
以上是关于TCP网络程序设计的主要内容,如果未能解决你的问题,请参考以下文章
VSCode自定义代码片段14——Vue的axios网络请求封装
VSCode自定义代码片段14——Vue的axios网络请求封装