C++---Socket网络编程代码实战初识
1.Socket一句话简介
套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。把复杂的TCP/IP协议族隐藏在socket接口后面,对开发者来说,只要用好socket相关的函数,就可以完成端到端的数据通信。
所以我Socket的流程弄清楚,各个函数的意义大致明白,不懂再查就很好容易上手。
1.1 Socket 流程
客户端和服务端想要进行通信的代码到底长什么样子呢,先不要着急看具体代码,下图的socket流程相信你看明白之后脑海里已经有了两个代码的大致结构,下面的每一个函数都相当于我们在调接口,只要描写相应的参数即可。
1.2 服务端的具体代码
在源码中我尽量的把每一步的作用解释清楚,后面我们再对每个函数展开讲解。代码里会出现多种数据结构,多个函数。对于入门来说了解socket通信的过程、读懂源码理解每段代码的用途和函数调用的功能,不要去纠缠这些结构体和函数的参数,因为这些参数基本固定。
1 #include <stdio.h> 2 #include <string.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 #include <netdb.h> 6 #include <sys/types.h> 7 #include <sys/socket.h> 8 #include <arpa/inet.h> 9 10 int main(int argc, char* argv[]) 11 { 12 if (argc != 2) //程序运行需传入参数:端口号 13 { 14 printf("Using:./server port\nExample:./server 5005\n\n"); return -1; 15 } 16 17 18 // 第1步:socket(),创建服务端的socket。socket()函数返回的是int 类型的文件描述符 -1说明未创建成功 19 int serverfd; 20 if ((serverfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); return -1; } 21 22 // 第2步:bind(),把服务端用于通信的地址和端口绑定到socket上。 23 struct sockaddr_in servaddr; // sockaddr_in 是一个数据结构,里面能存放地址和端口等信息 24 memset(&servaddr, 0, sizeof(servaddr)); // 初始化为0 25 servaddr.sin_family = AF_INET; // 协议族 26 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意ip地址。 27 //servaddr.sin_addr.s_addr = inet_addr("192.168.190.134"); // 指定ip地址。 28 servaddr.sin_port = htons(atoi(argv[1])); // 指定通信端口(运行程序时传入的参数)。 29 if (bind(serverfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0) //bind()成功返回的是0 30 { 31 perror("bind"); close(serverfd); return -1; 32 } 33 34 // 第3步:listen(),把socket设置为监听模式。 35 if (listen(serverfd, 5) != 0) { perror("listen"); close(serverfd); return -1; } 36 37 // 第4步:accept(),接受客户端的连接。 38 int clientfd; // 客户端的socket。 39 int socklen = sizeof(struct sockaddr_in); // struct sockaddr_in的大小 40 struct sockaddr_in clientaddr; // 客户端的地址信息。 41 clientfd = accept(serverfd, (struct sockaddr*)&clientaddr, (socklen_t*)&socklen); 42 printf("客户端(%s)已连接。\n", inet_ntoa(clientaddr.sin_addr)); 43 44 // 第5步:recv() 通信,接收客户端发过来的报文后,回复ok。 45 char buffer[1024]; 46 while (1) 47 { 48 int iret; 49 memset(buffer, 0, sizeof(buffer)); 50 if ((iret = recv(clientfd, buffer, sizeof(buffer), 0)) <= 0) // 接收客户端的请求报文。 51 { 52 printf("iret=%d\n", iret); break; 53 } 54 printf("接收:%s\n", buffer); 55 56 strcpy(buffer, "ok"); 57 if ((iret = send(clientfd, buffer, strlen(buffer), 0)) <= 0) // 向客户端发送响应结果。 58 { 59 perror("send"); break; 60 } 61 printf("发送:%s\n", buffer); 62 } 63 64 // 第6步:close(),关闭socket,释放资源。 65 close(serverfd); close(clientfd); 66 67 }
1.2.1 socket()函数解析