前言:
今天各位老铁们对“c语言socket文件传输”都比较关注,看官们都想要了解一些“c语言socket文件传输”的相关知识。那么小编同时在网摘上网罗了一些有关“c语言socket文件传输””的相关内容,希望你们能喜欢,看官们快快来了解一下吧!基于Linux下C语言的Socket网络编程
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
Socket被广泛用作网络通信,它几乎支持所有的编程语言,各种语言对于Socket操作流程也比较类似。 服务端程序的创建流程为创建socket——绑定端口号——监听——接受连接——读和写; 客户端程序的创建流程为创建socket——通过IP和端口连接服务端——读和写。 [TOC]
服务端1. 创建Socket
包含头文件: #include <sys/socket.h> #include <sys/types.h> 函数原型:int socket(int domain, int type, int protocol); socket函数里有三个参数。 domain选择通信协议族,常用的有以下几种。
Name Purpose
AF_UNIX, AF_LOCAL Local communication
AF_INET(常用) IPv4 Internet protocols
AF_INET6 IPv6 Internet protocols
type指定Socket类型,常用以下几种。
Name Purpose
SOCK_STREAM 流式套接字(TCP协议)
SOCK_DGRAM 数据报式套接字(UDP协议)
protocol指定协议,常用以下几种
NAME Purpose
IPPROTO_TCP TCP传输协议
IPPROTO_UDP UDP传输协议
IPPROTO_STCP STCP传输协议
IPPROTO_TIPC TIPC传输协议
type和protocol不可以随意组合,当第三个参数type为 0自动选择第二个参数对应的默认协议
Socket如果创建成功,则返回一个描述该网络通信端点的文件描述符,操作系统会自动分配当前最小可用的文件描述符。
示例代码
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
2. 绑定端口号和IP地址
包含头文件:
#include <sys/socket.h>
#include <sys/types.h>
函数原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
bind()函数把地址族中的特定地址赋给socket。
sockfdsocket描述字,通过socket创建,标识唯一一个服务端描述字。
sockaddr结构体,通过初始化sockaddr_in结构体然后进行强制类型转化。示例代码如下:
struct sockaddr_in *server_socket = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));memset(server_socket, 0, sizeof (struct sockaddr_in)); // 清空sockaddr_in 结构体server_socket->sin_addr.s_addr = htonl(INADDR_ANY); // 任意IP地址server_socket->sin_family = AF_INET; // 使用IPv4协议族server_socket->sin_port = htons(PORT); // 端口号
addrlen为sockaddr的长度。
bind示例代码如下
bind(sockfd, (struct sockaddr *)server_socket, sizeof (struct sockaddr));
3. 连接和监听
包含头文件:
#include <sys/socket.h>
#include <sys/types.h>
函数原型int listen(int sockfd, int backlog);
sockfd为服务端建立socket的文件描述符
backlog为对应socket可以排队的最大连接数
服务端调用listen()函数监听socket,当客户端通过connect()函数连接服务端,发送连接请求时,listen()就会监听到这个请求。
4. 接受客户端连接
包含头文件:
#include <sys/socket.h>
#include <sys/types.h>
函数原型int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockfd为服务端打开的socket描述字
addr用于保存连接的客户端的IP地址和端口号,其内容与sockaddr结构体类似。
addrlen是接受地址的长度。
accept()函数如果执行成功,则返回一个由内核生成的全新的套接字,用于和新客户端之间通信。
5. 读和写
包含头文件:
#include <unistd.h>
函数原型:ssize_t read(int fd, void *buf, size_t count);
函数原型:ssize_t write(int fd, const void *buf, size_t count);
当socket打开网络描述字后,程序可以像读写文件一样向网络描述字读或者写,对应接受和发送数据。
客户端1. 创建socket
过程同服务端,socket返回的套接字描述符将直接用于和对端通信。
2. 连接服务器
函数原型int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); sockfd为客户端建立socket的文件描述符 addr为sockaddr结构体保存的服务端的IP地址和端口号,以及协议类型,例如:
struct sockaddr_in *server_addr = (struct sockaddr_in *)malloc(sizeof (struct sockaddr_in)); memset(server_addr, 0, sizeof (struct sockaddr_in)); server_addr->sin_family = AF_INET; // 使用IPv4协议族server_addr->sin_port = htons(port); // port为服务器绑定的端口号inet_pton(AF_INET, "xxx.xxx.xxx.xxx", &server_addr->sin_addr); // 服务端的IP地址
客户端发起tcp连接请求,服务端监听到请求并接受请求后,TCP连接建立即可以开始传输文件。(如果使用UDP协议有些许区别,暂时不做讨论。)
3.发送数据
连接建立后,客户端通过write()和write()函数向打开的sockfd发送或接受数据
代码示例Server
#include <stdio.h>#include <sys/socket.h>#include <sys/types.h>#include <sys/select.h>#include <arpa/inet.h>#include <netinet/in.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#define PORT 8000int main(){ // 创建socket int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 申请服务端和客户端地址结构体空间,客户端地址用于保存新连接的地址端口信息 struct sockaddr_in *server_socket = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in)); struct sockaddr_in *client_socket = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in)); socklen_t client_address_len; memset(server_socket, 0, sizeof (struct sockaddr_in)); memset(client_socket, 0, sizeof (struct sockaddr_in)); server_socket->sin_addr.s_addr = htonl(INADDR_ANY); server_socket->sin_family = AF_INET; server_socket->sin_port = htons(PORT); // 绑定 bind(sockfd, (struct sockaddr *)server_socket, sizeof (struct sockaddr)); // 监听 listen(sockfd, 20); // 接受 int connect_fd = accept(sockfd, (struct sockaddr *)client_socket, &client_address_len); char buf[] = "Hello Wrold!"; // 发送 while(write(connect_fd, buf, strlen(buf))) { printf("send msg: %s\n", buf); sleep(1); } return 0;}Client
#include <stdio.h>#include <sys/socket.h>#include <sys/types.h>#include <sys/select.h>#include <arpa/inet.h>#include <netinet/in.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>int main(){ // 创建socket int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 准备地址结构体 struct sockaddr_in *server_addr = (struct sockaddr_in *)malloc(sizeof (struct sockaddr_in)); memset(server_addr, 0, sizeof (struct sockaddr_in)); server_addr->sin_family = AF_INET; server_addr->sin_port = htons(8000); inet_pton(AF_INET, "127.0.0.1", &server_addr->sin_addr); // 连接 connect(sockfd, (struct sockaddr *)server_addr, sizeof (struct sockaddr)); // sockaddr_in强制转换成sockaddr char buf[1024] = ""; // 读取 while(read(sockfd, buf, 1024)) { printf("recv msg: %s\n", buf); memset(buf, 0, 1024); } return 0;}最后小编建了一个c/c++ Linux的学习技术交流群,会不定期的分享一些视频学习资料:主要有C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK技术,面试技巧方面的资料。
感兴趣的朋友可以后台私信【架构】获取
标签: #c语言socket文件传输