网络编程基础
1. socket基础编程
1.1 TCP Server网络编程基本步骤
1.创建socket,指定使用TCP协议
2.将socket与地址和端口绑定
3.监听端口
4.创建连接socket
5.使用recv接收数据
6.使用send发送数据
7.使用close关闭连接
1.2 TCP常见套接字选项
1. SO_REUSEADDR端口处于time_wait时,仍然可以启动,无需等待连接的FIN标识;
2. SO_RECVBUF/SO_SNDBUF
1.3 TCP通信
1.3.1 TCP服务端实现
1 /** 2 tcpserver.c 3 */ 4 5 /** 6 struct sockaddr_in 7 { 8 sa_family_t sin_family; 9 uint16_t sin_port; 10 struct in_addr sin_addr; 11 char sin_zero[8]; 12 } 13 14 struct in_addr 15 { 16 in_addr_t s_addr; 17 } 18 19 struct sockaddr 20 { 21 sa_family_t sin_family; 22 char sin_zero[14]; 23 } 24 */ 25 #include <stdio.h> 26 #include <strings.h> 27 #include <string.h> 28 #include <unistd.h> 29 #include <netinet/in.h> 30 #include <sys/types.h> 31 #include <sys/socket.h> 32 33 #define PORT 8111 34 #define MESSAGE_LEN 1024 35 36 int main(int argc, char* argv[]) 37 { 38 int socket_fd; 39 int accept_fd; 40 int on = 1; 41 int ret = -1; 42 int backlog = 10; 43 char in_buff[MESSAGE_LEN] = { 0 }; 44 struct sockaddr_in localaddr, remoteaddr; 45 46 socket_fd = socket(AF_INET, SOCK_STREAM, 0); 47 if (socket_fd == -1) { 48 printf("can't create socket fd\n"); 49 _exit(-1); 50 } 51 52 ret = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 53 if (ret == -1) { 54 printf("faild to set socket option\n"); 55 } 56 57 localaddr.sin_family = AF_INET; 58 localaddr.sin_port = htons(PORT); 59 localaddr.sin_addr.s_addr = htonl(INADDR_ANY); 60 bzero(localaddr.sin_zero, 8); 61 socklen_t addr_len = sizeof(struct sockaddr_in); 62 ret = bind(socket_fd, (struct sockaddr *)&localaddr, addr_len); 63 if (ret == -1) { 64 printf("failed to bind addr\n"); 65 _exit(-1); 66 } 67 68 ret = listen(socket_fd, backlog); 69 if (ret == -1) { 70 printf("failed listen\n"); 71 _exit(-1); 72 } 73 74 while (1) { 75 accept_fd = accept(socket_fd, (struct sockaddr *)&remoteaddr, &addr_len); 76 if (accept_fd <= 0) continue; 77 78 while (1) { 79 memset(in_buff, 0, sizeof(in_buff)); 80 ret = recv(accept_fd, (void *)in_buff, MESSAGE_LEN, 0); 81 if (ret == 0) break; 82 83 printf("recv[%s|%d]\n", in_buff, ret); 84 send(accept_fd, (void *)in_buff, strlen(in_buff), 0); 85 } // end while 86 87 close(accept_fd); 88 } //end while 89 90 close(socket_fd); 91 92 return 0; 93 } 94 95 # gcc -std=c11 -g -o tcpserver tcpserver.c 96 # ./tcpserver
1.3.2 TCP 客户端实现
1.创建socket,指定使用TCP协议;
2.使用connect连接服务器;
3.使用send/recv发送/接受数据;
4.关闭socket。
1 /** 2 tcpclient.c 3 */ 4 #include <stdio.h> 5 #include <unistd.h> 6 #include <string.h> 7 #include <sys/socket.h> 8 #include <sys/types.h> 9 #include <netinet/in.h> 10 #include <arpa/inet.h> 11 12 #define PORT 8111 13 #define MESSAGE_LEN 1024 14 15 int main(int argc, char* argv[]) 16 { 17 int ret = -1; 18 int socket_fd; 19 struct sockaddr_in server_addr; 20 socklen_t addr_len; 21 char send_buf[MESSAGE_LEN] = { 0 }; 22 char recv_buf[MESSAGE_LEN] = { 0 }; 23 24 socket_fd = socket(AF_INET, SOCK_STREAM, 0); 25 if (socket_fd < 0) { 26 printf("failed create socket\n"); 27 _exit(-1); 28 } 29 30 server_addr.sin_family = AF_INET; 31 server_addr.sin_port = htons(PORT); 32 server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 33 addr_len = sizeof(struct sockaddr_in); 34 ret = connect(socket_fd, (struct sockaddr *)&server_addr, addr_len); 35 if (ret < 0) { 36 printf("connect to server\n"); 37 _exit(-1); 38 } 39 40 while (1) { 41 memset(send_buf, 0, sizeof(send_buf)); 42 memset(recv_buf, 0, sizeof(recv_buf)); 43 //fgets(send_buf, MESSAGE_LEN, stdin); 44 gets(send_buf); 45 if (strncmp(send_buf, "quit", 4) == 0) 46 break; 47 48 ret = send(socket_fd, send_buf, strlen(send_buf), 0); 49 if (ret <= 0) { 50 printf("failed send msg[%s]\n", send_buf); 51 break; 52 } 53 54 ret = recv(socket_fd, recv_buf, sizeof(recv_buf), 0); 55 recv_buf[ret] = '\0'; 56 if (ret <= 0) { 57 printf("recv zero msg\n"); 58 continue; 59 } 60 61 printf("recv[%s|%d]\n", recv_buf, ret); 62 } // end while 63 64 close(socket_fd); 65 66 return 0; 67 } 68 69 # gcc -std=c11 -g -o tcpclient tcpclient.c 70 # ./tcpclient 127.0.0.1
1.4 UDP通信
1.4.1 UDP服务端实现
1.创建socket,指定使用UDP协议;
2.将socket与地址和端口绑定;
3.使用send/recv发送/接受数据;
4.使用close关闭连接。
1 /** 2 udpserver.c 3 */ 4 #include <stdio.h> 5 #include <sys/socket.h> 6 #include <sys/types.h> 7 #include <netinet/in.h> 8 #include <arpa/inet.h> 9 #include <strings.h> 10 11 #define PORT 8111 12 #define MSG_LEN 1024 13 14 int main(int argc, char* argv[]) 15 { 16 int sockfd; 17 socklen_t cli_len; 18 char msg[MSG_LEN] = { 0 }; 19 struct sockaddr_in serv_addr, cli_addr; 20 sockfd = socket(AF_INET, SOCK_DGRAM, 0); 21 22 bzero(&serv_addr, sizeof(serv_addr)); 23 serv_addr.sin_family = AF_INET; 24 serv_addr.sin_port = htons(PORT); 25 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 26 bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 27 28 while (1) { 29 int n = recvfrom(sockfd, msg, MSG_LEN, 0, (struct sockaddr *)&cli_addr, &cli_len); 30 if (n > 0) { 31 msg[n] = '\0'; 32 printf("recv[%s|%d]\n", msg, n); 33 sendto(sockfd, msg, n, 0, (struct sockaddr *)&cli_addr, cli_len); 34 } 35 } 36 37 return 0; 38 } 39 40 # gcc -std=c11 -g -o udpserver udpserver.c
41 # ./udpserver
1.4.2 UDP客户端实现
1 /** 2 udpclient.c 3 */ 4 #include <stdio.h> 5 #include <unistd.h> 6 #include <sys/socket.h> 7 #include <sys/types.h> 8 #include <arpa/inet.h> 9 #include <string.h> 10 #include <strings.h> 11 12 #define PORT 8111 13 #define MSG_LEN 1024 14 15 int main(int argc, char* argv[]) 16 { 17 int sockfd; 18 char send_buf[MSG_LEN] = { 0 }; 19 char recv_buf[MSG_LEN + 1] = { 0 }; 20 struct sockaddr_in serv_addr; 21 22 if (argc != 2) { 23 printf("usage: udpclient <ip address>\n"); 24 _exit(-1); 25 } 26 27 bzero(&serv_addr, sizeof(serv_addr)); 28 serv_addr.sin_family = AF_INET; 29 serv_addr.sin_port = htons(PORT); 30 inet_pton(AF_INET, argv[1], &serv_addr.sin_addr); 31 sockfd = socket(AF_INET, SOCK_DGRAM, 0); 32 33 while (fgets(send_buf, MSG_LEN, stdin) != NULL) { 34 sendto(sockfd, 35 send_buf, 36 strlen(send_buf), 37 0, 38 (struct sockaddr *)&serv_addr, 39 sizeof(serv_addr)); 40 int n = recvfrom(sockfd, recv_buf, MSG_LEN, 0, NULL, NULL); 41 if (n > 0) { 42 recv_buf[n] = '\0'; 43 printf("recv[%s|%d]\n", recv_buf, n); 44 //fputs(recv_msg, stdout); 45 } 46 } 47 48 return 0; 49 } 50 51 # gcc -std=c11 -g -o udpclient udpclient.c
52 # ./udpclient 127.0.0.1
注:gets()和fgets()不同的地方除了安全性外,还有就是gets()不会接收控制端的回车换行等不可见字符,fgets()则都会接收并发送。