TCP SERVER
1 #include <stdio.h>
2 #include <sys/socket.h>3 //#include <linux/in.h> // /usr/include/linux/in.h 或 /usr/include/i386-linux-gnu/sys/in.h 包含了struct sockaddr_in的定义
4 #include <unistd.h>
5 #include <netinet/in.h>
6 #include <arpa/inet.h>
7 #include <string.h>
8
9 #define NET_PORT 58850
10 #define NET_IP "127.0.0.1"
11 #define MAX_PEER 5
12
13 int main()
14 {
15 int socketfd = socket(AF_INET, SOCK_STREAM, 0);
16 //domain: AF_UNIX和AF_LOCAL都表示本地进程间的通信,不走网络协议。如果设为AF_INET表示进程间通信走ipv4的网络通信协议
17 //type: SOCK_STREAM表示网络通信采用TCP协议,通信前需要先建立连接。SOCK_DGRAM表示采用UDP协议,不建立连接直接通信。注意,即使本地通信,type的设置也会影响之后的通信的函数调用流程,不管是本地通信还是网络通信,只要时相同type的设置,之后的通信流程都是采用相同的函数调用过程
18
19 if (socketfd < 0) {
20 perror("create socketfd");
21 goto err_socketfd;
22 }
23
24 //类型声明见顶上include的in.h
25 //inet_addr把字符串形式的ip地址转换成32位整型类型的ip地址,同时进行大小端转换
26 //htons和ntohs都是16位数字的大小端转换,两者没有区别
27 //htonl和ntohl都是32位数字的大小端转换,两者也没有区别
28 struct sockaddr_in sockaddr = {29 .sin_family = AF_INET,
30 .sin_port = htons(NET_PORT),
31 .sin_addr = {
32 .s_addr = inet_addr(NET_IP),
33 },
34 };
35
36 //将sockaddr结构体里的信息传递给socketfd
37 //之前如果创建socketfd时,使用的是AF_UNIX或AF_LOCAL,表示通过一个本地文件进行进程通信,此时sockaddr接受的结构体是sockaddr_u n,里面存储的是本地文件的文件名和路径。如果之前使用的是AF_INET,那么此时接受的结构体是sockaddr_in,里面存储的是ip和端口号
38 if (bind(socketfd, (struct sockaddr *)&sockaddr, sizeof(struct sockaddr_in)) < 0) {
39 perror("bind");
40 goto err_bind;
41 }
42
43 if (listen(socketfd, MAX_PEER) < 0) {
44 perror("listen");
45 goto err_listen;
46 }
47
48 struct sockaddr_in client_addr;
49 socklen_t client_addr_len = sizeof(struct sockaddr_in);
50 int client_fd;
51 unsigned char rbuf = 0;
52 while (1) {
53 client_fd = accept(socketfd, (struct sockaddr*)&client_addr, &client_addr_len);
54 if (client_fd < 0) {
55 perror("accept");
56 goto err_accept;
57 }
58 printf("accept client: ip=%s, port=%d\n", inet_ntoa(client_addr.sin_addr), htons(client_addr.sin_port));
59 printf("server port=%d\n", htons(sockaddr.sin_port));
60 while (read(client_fd, &rbuf, 1)) {
61 write(STDOUT_FILENO, &rbuf, 1);
62 }
63 }
64
65 close(socketfd);
66 return 0;
67
68 err_accept:
69 err_listen:
70 err_bind:
71 close(socketfd);
72 err_socketfd:
73 return -1;
74 }
CLIENT
1 #include <stdio.h>
2 #include <sys/socket.h>
3 //#include <linux/in.h> // /usr/include/linux/in.h 或 /usr/include/i386-linux-gnu/sys/in.h 包含了struct sockaddr_in的定义
4 #include <unistd.h>
5 #include <netinet/in.h>
6 #include <arpa/inet.h>
7 #include <string.h>
8
9 #define NET_PORT 58850
10 #define NET_IP "192.168.0.201"
11 #define MAX_PEER 5
12
13 int main()
14 {
15 int socketfd = socket(AF_INET, SOCK_STREAM, 0);
16 //domain: AF_UNIX和AF_LOCAL都表示本地进程间的通信,不走网络协议。如果设为AF_INET表示进程间通信走ipv4的网络通信协议
17 //type: SOCK_STREAM表示网络通信采用TCP协议,通信前需要先建立连接。SOCK_DGRAM表示采用UDP协议,不建立连接直接通信。注意,即使本地通信,type的设置也会影响之后的通信的函数调用流程,不管是本地通信还是网络通信,只要时相同type的设置,之后的通信流程都是采用相同的函数调用过程
18
19 if (socketfd < 0) {
20 perror("create socketfd");
21 goto err_socketfd;
22 }
23
24 //类型声明见顶上include的in.h
25 //inet_addr把字符串形式的ip地址转换成32位整型类型的ip地址,同时进行大小端转换
26 //htons和ntohs都是16位数字的大小端转换,两者没有区别
27 //htonl和ntohl都是32位数字的大小端转换,两者也没有区别
28 struct sockaddr_in server_addr = {
29 .sin_family = AF_INET,
30 .sin_port = htons(NET_PORT),
31 .sin_addr = {
32 .s_addr = inet_addr(NET_IP),
33 },
34 };
35
36 if (connect(socketfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) < 0) {
37 perror("connect");
38 goto err_connect;
39 }
40
41 const char *welcome_msg = "hello world\n";
42 write(socketfd, welcome_msg, strlen(welcome_msg) + 1);
43
44 close(socketfd);
45 return 0;
46
47 err_connect:
48 err_bind:
49 close(socketfd);
50 err_socketfd:
51 return -1;
52 }