C语言中进行网络编程的步骤大致如下:
- 创建socket
- 绑定到一个IP地址和端口号
- 监听客户端请求
- 接受客户端连接
- 发送和接收数据
下面是详细的介绍:
- 创建socket
在C中使用socket函数来创建socket,语法如下:
int socket(int domain, int type, int protocol);
其中,domain参数指定了协议域,常用的有AF_INET(IPv4)和AF_INET6(IPv6)。type参数指定了数据传输方式,常用的有SOCK_STREAM(面向连接的 TCP socket)和SOCK_DGRAM(无连接的 UDP socket)。protocol参数通常设为0,表示由系统自动选择合适的协议。
例如,创建一个TCP socket:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
- 绑定到一个IP地址和端口号
在C中使用bind函数来将socket绑定到一个IP地址和端口号上,语法如下:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
其中,sockfd为要绑定的socket的文件描述符,addr为一个指向sockaddr结构体的指针,用来指定IP地址和端口号,addrlen为存储地址长度的变量。
例如,将socket绑定到本地IP地址的8080端口上:
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080); // 将主机字节序转换为网络字节序
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 使用INADDR_ANY绑定到所有可用的地址
bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
- 监听客户端请求
在C中使用listen函数来监听socket,语法如下:
int listen(int sockfd, int backlog);
其中,sockfd为要监听的socket的文件描述符,backlog为等待连接队列的最大长度。
例如,监听socket:
listen(sockfd, 10); // backlog设为10,表示等待连接队列的最大长度为10
- 接受客户端连接
在C中使用accept函数来接受客户端连接,语法如下:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
其中,sockfd为要接受连接的socket的文件描述符,addr为一个指向sockaddr结构体的指针,用来存储客户端的IP地址和端口号,addrlen为存储地址长度的变量。
例如,接受客户端连接:
struct sockaddr_in client_addr;
socklen_t client_addrlen = sizeof(client_addr);
int connfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addrlen);
printf("got connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
其中,inet_ntoa函数将IP地址的网络字节序整数转换为字符串形式。
- 发送和接收数据
在C中使用send和recv函数来发送和接收数据,语法如下:
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
其中,sockfd为要发送/接收数据的socket的文件描述符,buf为数据缓冲区的地址,len为数据长度,flags为选项,通常设为0。
例如,向客户端发送数据:
send(connfd, "welcome to my server", strlen("welcome to my server"), 0);
接收客户端发送的数据:
char buffer[1024];
recv(connfd, buffer, sizeof(buffer), 0);
printf("received: %s\n", buffer);
下面是两个示例:
示例1:简单的TCP服务器和客户端
// server.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main() {
// 创建socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
// 绑定到本地IP地址的8080端口上
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
// 监听socket
listen(sockfd, 10);
// 接受客户端连接,并发送欢迎消息
while (1) {
struct sockaddr_in client_addr;
socklen_t client_addrlen = sizeof(client_addr);
int connfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addrlen);
printf("got connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
send(connfd, "welcome to my server\n", strlen("welcome to my server\n"), 0);
// 接收客户端消息,并输出
char buffer[1024];
while (1) {
int ret = recv(connfd, buffer, sizeof(buffer), 0);
if (ret <= 0) {
break;
}
buffer[ret] = '\0';
printf("received: %s\n", buffer);
}
// 关闭连接
close(connfd);
}
// 关闭socket
close(sockfd);
return 0;
}
// client.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main() {
// 创建socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
// 连接到本地IP地址的8080端口上
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
// 接收服务器消息,并输出
char buffer[1024];
ssize_t ret = recv(sockfd, buffer, sizeof(buffer), 0);
if (ret > 0) {
buffer[ret] = '\0';
printf("received: %s", buffer);
}
// 向服务器发送消息
send(sockfd, "hello\n", strlen("hello\n"), 0);
// 关闭socket
close(sockfd);
return 0;
}
示例2:简单的UDP服务器和客户端
// server.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main() {
// 创建socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
// 绑定到本地IP地址的8080端口上
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
// 接收客户端消息,并回复
struct sockaddr_in client_addr;
socklen_t client_addrlen = sizeof(client_addr);
char buffer[1024];
while (1) {
int ret = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &client_addrlen);
if (ret == -1) {
perror("recvfrom");
break;
}
buffer[ret] = '\0';
printf("received: %s\n", buffer);
sendto(sockfd, "got it\n", strlen("got it\n"), 0, (struct sockaddr *)&client_addr, client_addrlen);
}
// 关闭socket
close(sockfd);
return 0;
}
// client.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main() {
// 创建socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
// 向服务器发送消息
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
sendto(sockfd, "hello\n", strlen("hello\n"), 0, (struct sockaddr *)&addr, sizeof(addr));
// 接收服务器回复,并输出
char buffer[1024];
struct sockaddr_in recv_addr;
socklen_t recv_addrlen = sizeof(recv_addr);
int ret = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&recv_addr, &recv_addrlen);
if (ret > 0) {
buffer[ret] = '\0';
printf("received: %s", buffer);
}
// 关闭socket
close(sockfd);
return 0;
}
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言中如何进行网络编程? - Python技术站