Cpp网络通信01-基本的Socket通信

Cpp网络通信01-基本的Socket通信

服务端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

using namespace std;

int main(int argc, char *argv[]) {

if (argc != 2) {
printf("usage:\n\t./Server <服务端端口>\n");
return -1;
}

printf("Hello Server!\n");

// 1.创建服务端的socket
// AF_INET: ipv4 SOCK_STREAM: 流模式(TCP)
int listenFd = socket(AF_INET, SOCK_STREAM, 0);
if (listenFd == -1) {
perror("socket");
exit(-1);
}

// 2.把服务端用于通信的IP和端口绑定到socket上
struct sockaddr_in serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET; // ipv4
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 表示接收所有地址的请求
serverAddr.sin_port = htons(atoi(argv[1])); // 服务器端口
// 绑定
if (bind(listenFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) != 0) {
perror("bind");
close(listenFd);
return -1;
}

// 3.把socket设置为监听状态
if (listen(listenFd, 5) != 0) {
perror("listen");
close(listenFd);
return -1;
}

cout << "监听端口: " << argv[1] << endl;

// 4.手里客户端的连接请求, accept是阻塞的
int clientFd = accept(listenFd, 0, 0);
if (clientFd == -1) {
perror("accept");
close(listenFd);
return -1;
}

cout << "客户端已连接\n";

// 5.与客户端通信,接收客户端发过来的报文后,回复ok.
char buffer[1024];
while (true) {
int iret;
memset(buffer, 0, sizeof(buffer));
// 接收客户端的请求报文,recv同样是阻塞的
// 如果客户端断开连接,recv()返回0
if ((iret = recv(clientFd, buffer, sizeof(buffer), 0)) <= 0) {
cout << "iret=" << iret << endl;
break;
}
cout << "接收: " << buffer << endl;

strcpy(buffer, "ok"); // 生成回应报文
// 向客户端发送回应报文
if ((iret = send(clientFd, buffer, strlen(buffer), 0)) <= 0) {
perror("send");
break;
}
cout << "发送: " << buffer << endl;
}
// 6.关闭socket
close(listenFd);
close(clientFd);
return 0;
}

客户端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <iterator>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

using namespace std;

int main(int argc, char *argv[]) {

if (argc != 3) {
cout << "Usage:\n\t./Client <服务端IP> <服务端端口>\n";
return -1;
}

cout << "连接到 " << argv[1] << ":" << argv[2] << endl;

// 1.创建客户端的socket
int socketFd = socket(AF_INET, SOCK_STREAM, 0);
if (socketFd == -1) {
perror("socket");
return -1;
}


// 2.向服务器发起连接请求
struct hostent* h; // 用于存放服务端ip
if ((h = gethostbyname(argv[1])) == 0) {
perror("gethostbyname");
close(socketFd);
return -1;
}
struct sockaddr_in serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
memcpy(&serverAddr.sin_addr, h->h_addr, h->h_length);
serverAddr.sin_port = htons(atoi(argv[2]));
if (connect(socketFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) != 0) {
perror("connect");
close(socketFd);
return -1;
}

// 3.与服务器通信,发送一个请求报文后等待回复,然后再发下一个报文
char buffer[1024];
for (int i = 0; i < 3; i++) {
int iret;
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "这是第%d条报文", i + 1);

if ((iret = send(socketFd, buffer, strlen(buffer), 0)) <= 0) {
perror("send");
break;
}
cout << "发送: " << buffer << endl;

memset(buffer, 0, sizeof(buffer));
// 接收服务端的回应,recv会阻塞
if ((iret = recv(socketFd, buffer, sizeof(buffer), 0)) <= 0) {
cout << "iret=" << iret << endl;
break;
}
cout << "接收: " << buffer << endl;
}
// 4.关闭socket
close(socketFd);
return 0;
}

Cpp网络通信01-基本的Socket通信
https://chordfish-k.github.io/2024/12/29/cpp/cpp-webserver01/
作者
超弦鱼
发布于
2024年12月29日
许可协议