1、网络协议分层模型:网络编程的基础是网络协议分层模型,其中最著名的是OSI七层模型和TCP/IP四层模型,这些模型将网络通信划分为不同的层次,每层负责不同的功能,物理层负责传输原始比特流,数据链路层负责在相邻节点之间可靠地传输数据,网络层负责数据包从源到目的地的传输和路由选择,传输层负责提供端到端的可靠数据传输服务。
2、IP地址和端口号:在网络中,每个设备都有一个唯一的IP地址,用于标识网络中的设备,端口号则用于标识设备上的不同服务或应用程序,IP地址分为IPv4和IPv6两种格式,端口号范围为0-65535,其中0-1023为系统端口,1024-49151为注册端口,49152-65535为动态或私有端口。
3、套接字(Socket):套接字是网络编程中的基本抽象,它代表了一个网络连接的一端,在C语言中,套接字用于实现网络通信,根据通信方式的不同,套接字可以分为流式套接字(TCP)、数据报套接字(UDP)等。
4、网络字节序与主机字节序:由于不同计算机体系结构可能采用不同的字节序(大小端),网络通信需要统一字节序,网络字节序通常采用大端字节序,在C语言中,可以使用相关函数进行字节序转换。
1、TCP协议简介:TCP(传输控制协议)是一种面向连接、可靠的传输层协议,它通过三次握手建立连接,确保数据的可靠传输。
2、TCP套接字编程步骤
服务器端
创建套接字:使用socket()函数创建一个TCP套接字。
绑定地址:使用bind()函数将套接字与IP地址和端口号绑定。
监听连接:使用listen()函数监听客户端连接请求。
接受连接:使用accept()函数接受客户端连接,创建一个新的套接字用于与客户端通信。
数据传输:使用read()和write()函数(或recv()和send()函数)进行数据传输。
关闭套接字:使用close()函数关闭套接字。
客户端
创建套接字:使用socket()函数创建一个TCP套接字。
连接服务器:使用connect()函数连接服务器。
数据传输:使用read()和write()函数(或recv()和send()函数)进行数据传输。
关闭套接字:使用close()函数关闭套接字。
3、代码案例:以下是一个简单的TCP回显服务器和客户端的示例代码。
服务器端代码
#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}; // 创建套接字 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 绑定地址和端口 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); if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连接 if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } // 数据传输 while (1) { read(new_socket, buffer, BUFFER_SIZE); printf("Server received: %s ", buffer); write(new_socket, buffer, strlen(buffer)); memset(buffer, 0, BUFFER_SIZE); } // 关闭套接字 close(new_socket); close(server_fd); return 0; }
客户端代码
#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 sock = 0; struct sockaddr_in serv_addr; 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); // 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 "); read(sock, buffer, BUFFER_SIZE); printf("%s ",buffer ); // 关闭套接字 close(sock); return 0; }
1、问:什么是网络字节序?为什么需要它?
答:网络字节序是指网络通信中规定的字节序,通常采用大端字节序,由于不同计算机体系结构可能采用不同的字节序(如大端和小端),为了确保网络通信的正确性,需要统一字节序,网络字节序的存在使得不同体系结构的计算机能够正确解析和处理网络数据。
2、问:TCP和UDP有什么区别?
答:TCP(传输控制协议)是一种面向连接的、可靠的协议,它提供了数据的顺序传输、无差错、不丢失、不重复等功能,而UDP(用户数据报协议)是一种无连接的、不可靠的协议,它只提供简单的消息传递服务,不保证数据的可靠性和顺序性,TCP适用于需要可靠传输的应用,如HTTP、FTP等;而UDP适用于对实时性要求较高、对数据可靠性要求较低的应用,如视频直播、在线游戏等。