C 语言网络编程是利用 C 语言进行网络应用程序开发的过程,它主要依赖于套接字(Socket)编程接口来实现网络通信,以下是关于 C 语言网络编程的详细内容:
1、网络协议:网络编程基于网络协议,如 TCP/IP 协议族,TCP 提供可靠的、面向连接的传输服务,适用于需要高可靠性的应用;UDP 则提供无连接的服务,数据传输速度较快但不如 TCP 可靠。
2、套接字:套接字是网络编程的核心,它是操作系统提供的一种网络通信接口,通过套接字,程序可以在网络中发送和接收数据,套接字分为流套接字(用于 TCP 连接)和数据报套接字(用于 UDP 通信)。
1、创建套接字:使用socket()
函数创建一个套接字,该函数返回一个套接字描述符,如果失败则返回 -1。
int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); }
2、绑定套接字:对于服务器端程序,需要将套接字绑定到一个特定的 IP 地址和端口号上,使用bind()
函数实现,这一步对客户端程序通常不是必须的。
struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); serv_addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("socket bind failed"); exit(EXIT_FAILURE); }
3、监听和接受连接:服务器端需要监听端口,等待客户端的连接请求,并使用accept()
函数接受连接。listen()
函数使套接字进入被动打开状态,准备接受连接。
if (listen(sockfd, 5) < 0) { perror("Listen failed"); exit(EXIT_FAILURE); } int new_socket = accept(sockfd, (struct sockaddr *)&address, (socklen_t*)&addrlen); if (new_socket < 0) { perror("Accept failed"); exit(EXIT_FAILURE); }
4、发送和接收数据:无论是客户端还是服务器端,都需要使用send()
或recv()
函数来发送和接收数据。
char buffer[1024] = {0}; read(new_socket, buffer, 1024); printf("%s ", buffer); char *message = "Hello from server"; send(new_socket, message, strlen(message), 0);
5、关闭套接字:通信结束后,应关闭套接字以释放资源,使用close()
函数。
close(new_socket); close(sockfd);
以下是一个简单的 TCP 服务器和客户端的例子:
1、TCP 服务器:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #define PORT 8080 int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; char *message = "Hello from server"; // Creating socket file descriptor if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // Forcefully attaching socket to the port 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); // Bind the socket to the address and port number specified in address structure if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) { perror("bind failed"); exit(EXIT_FAILURE); } // Start listening for client connections. Here, the backlog queue is set to 3 if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } // Accept a connection from a client if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("accept"); exit(EXIT_FAILURE); } // Read data sent by the client from the socket into the buffer array and print it on the console read(new_socket, buffer, 1024); printf("%s ",buffer ); // Send a response back to the client using the same socket that was used to receive the data from the client send(new_socket, message, strlen(message), 0); printf("Hello message sent "); return 0; }
2、TCP 客户端:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #define PORT 8080 int main() { struct sockaddr_in address; int sock = 0; struct sockaddr_in serv_addr; char *hello = "Hello from client"; char buffer[1024] = {0}; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf(" Socket creation error "); return -1; } memset(&serv_addr, '0', sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); // Convert IPv4 and IPv6 addresses from text to binary form 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, 1024); printf("%s ",buffer ); return 0; }
1、问题:为什么在调用socket()
函数时会失败?
回答:可能的原因包括指定的协议族不支持、系统资源不足等,请检查错误信息以确定具体原因。
2、问题:如何选择合适的协议和套接字类型?
回答:这取决于应用的需求,如果需要可靠的数据传输,应选择 TCP;如果需要快速但不可靠的传输,可以选择 UDP,根据传输的数据类型选择合适的套接字类型。