c 的网络通信例程
- 行业动态
- 2025-01-31
- 2
一、基本原理
网络通信是指通过计算机网络将数据从一个节点传递到另一个节点的过程,在网络通信中,涉及到协议、端口、套接字等重要概念,常见的网络通信协议包括TCP/IP、UDP等。
二、核心函数
1、socket:创建一个套接字,用于建立网络连接。
基本语法:SOCKET socket(int af, int type, int protocol);
参数说明:
af
:地址族,值包含AF_INET
(IPv4)、AF_INET6
(IPv6)等。
type
:数据传输方式/套接字类型,值包含SOCK_STREAM
(流格式套接字/面向连接的套接字)、SOCK_DGRAM
(数据报套接字/无连接的套接字)等。
protocol
:传输协议,值包含IPPROTO_TCP
(TCP传输协议)、IPPROTO_UDP
(UDP传输协议)等。
2、bind:将套接字与特定的IP地址和端口绑定起来,以便接收数据。
基本语法:int bind(SOCKET sock, const struct sockaddr *addr, int addrlen);
参数说明:
sock
:服务器套接字对象。
addr
:sockaddr
结构体变量的指针。
addrlen
:为addr
变量的大小。
3、listen:让套接字进入被动监听状态。
基本语法:int listen(SOCKET socket, int backlog);
参数说明:
socket
:服务器套接字对象(进入监听状态)。
backlog
:请求队列的最大长度。
4、accept:当套接字处于监听状态时,可以通过此函数来接收客户端请求,该函数返回一个新的套接字来和客户端通信。
基本语法:SOCKET accept(SOCKET sock, struct sockaddr *addr, int *addrlen);
参数说明:
sock
:服务器套接字对象。
addr
:sockaddr_in
结构体变量。
addrlen
:addr
的长度。
5、connect:将套接字与服务器端的IP地址和端口绑定起来建立连接。
基本语法:int connect(SOCKET sock, const struct sockaddr* serv_addr, int addrlen);
参数说明:
sock
:客户端套接字对象。
serv_addr
:sockaddr_in
结构体变量的指针。
addrlen
:为addr
变量的大小。
6、send:专门的发送数据的函数。
基本语法:int send(SOCKET sock, const char *buf, int len, int flags);
参数说明:
sock
:要发送数据的套接字对象。
buf
:要发送的数据的缓冲区地址。
len
:为要发送的数据的字节数。
flags
:为发送数据时的选项,参数值一般设置为0或NULL。
7、recv:专门的接收数据的函数。
基本语法:int recv(SOCKET sock, char *buf, int len, int flags);
参数说明:
sock
:要接收数据的套接字对象。
buf
:要接收的数据的缓冲区地址。
len
:为要接收的数据的字节数。
flags
:为接收数据时的选项,参数值一般设置为0或NULL。
8、sockaddr_in:结构体用来处理网络通信的地址。
基本语法:
struct sockaddr_in { sa_family_t sin_family; //地址族(Address Family),也就是地址类型 uint16_t sin_port; //16位的端口号 struct in_addr sin_addr; //IP地址 char sin_zero[8]; //填充0以保持与struct sockaddr同样大小 };
三、服务器端通信步骤
1、创建套接字:使用socket()
函数创建一个套接字。
2、绑定地址:使用bind()
函数将套接字与特定的IP地址和端口绑定起来。
3、监听连接:对于服务器端,需要使用listen()
函数监听连接请求。
4、接受连接:当有客户端请求连接时,服务器可以通过accept()
函数来接受连接。
5、接收客户端消息:使用recv()
函数接收客户端发送的消息。
6、向客户端发送消息:使用send()
函数向客户端发送消息。
7、关闭连接:通信完成后,使用close()
函数关闭套接字,释放资源。
四、客户端通信步骤
1、创建套接字:使用socket()
函数创建一个套接字。
2、连接服务器:使用connect()
函数与服务器建立连接。
3、向服务器发送消息:使用send()
函数向服务器发送消息。
4、接收服务器推送的消息:使用recv()
函数接收服务器推送的消息。
5、关闭客户端与服务器端通信:使用close()
函数关闭套接字,释放资源。
五、示例代码
以下是一个使用C语言实现的简单TCP通信程序示例,包括服务器端和客户端的代码。
服务器端代码(server.c)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define PORT 8080 #define BUFFER_SIZE 1024 int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[BUFFER_SIZE] = {0}; const char *hello = "Hello from server"; // 创建套接字文件描述符 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 强制附加套接字到端口8080 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // 将套接字绑定到端口8080 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) { perror("bind failed"); exit(EXIT_FAILURE); } // 开始监听是否有客户端连接,最多允许3个客户端同时连接 if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } // 接受一个客户端的连接请求,并为其创建一个新的套接字new_socket if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("accept"); exit(EXIT_FAILURE); } // 读取客户端发送的消息,并打印出来 read(new_socket, buffer, BUFFER_SIZE); printf("%s ",buffer ); // 向客户端发送消息 send(new_socket, hello, strlen(hello), 0); printf("Hello message sent "); // 关闭套接字连接 close(new_socket); close(server_fd); return 0; }
客户端代码(client.c)
#include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #define PORT 8080 #define BUFFER_SIZE 1024 int main() { struct sockaddr_in serv_addr; int sock = 0; char *hello = "Hello from client"; char buffer[BUFFER_SIZE] = {0}; // 创建套接字文件描述符 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf(" Socket creation error "); return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); // 将套接字与服务器端的IP地址和端口绑定起来建立连接 if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) { printf(" Invalid address/ Address not supported "); return -1; } if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf(" Connection Failed "); return -1; } send(sock, hello, strlen(hello), 0); printf("Hello message sent "); int valread = read(sock, buffer, BUFFER_SIZE); printf("%s ",buffer ); // 关闭套接字连接 close(sock); return 0; }