Client/Server Programming Pattern
- The server remains on the network for a long time (disclosing its own IP address) and waits for the client to connect
- The client initiates a connection action and waits for the server to respond
Features:
- The server cannot actively connect to the client
- The client can only connect to the server in a predefined way (protocol)
server-side programming
1. 准备网络连接
2. 绑定端口
3. 进入端口监听状态
4. 等待连接
The core work of the server: binding & listening & receiving
- Binding:
int bind(int sock, struct sockaddr *addr, socklen_t addrlen);
- Monitor:
int listen(int sock, int backlog);
- Receive:
int accept(int sock, struct sockaddr *addr, socklen_t addrlen);
In-depth analysis of the server
- The server socket is only used for receiving connections, not for actual communication
- When a connection is received, the accept() function returns the socket to communicate with the client
- Server socket generates client socket for communication
So, what exactly is a socket? How to understand?
Deep understanding of socket() function
what is socket()?
- socket() is a multifunctional function
What does socket() return?
- The return value of socket() is the resource identifier used for communication
What else can socket() do?
- socket() can provide different types of communication functions (local inter-process communication)
Programming experiment: first experience of server-side programming
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int server = 0;
struct sockaddr_in saddr = {0};
int clinet = 0;
struct sockaddr_in caddr = {0};
socklen_t asize = 0;
int len = 0;
char buf[32] = {0};
int r = 0;
server = socket(PF_INET, SOCK_STREAM, 0);
if (server == -1) {
printf("server socket error\n");
return -1;
}
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.sin_port = htons(8899);
if (bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
printf("server bind error\n");
return -1;
}
if (listen(server, 1) == -1) {
printf("server listen error\n");
return -1;
}
printf("server start success\n");
asize = sizeof(caddr);
clinet = accept(server, (struct sockaddr*)&caddr, &asize);
if (clinet == -1) {
printf("client accept error\n");
return -1;
}
printf("client: %d\n", clinet);
len = 0;
do {
int i = 0;
r = recv(clinet, buf, sizeof(buf), 0);
if (r > 0) {
len += r;
}
for (i=0; i<r; ++i) {
printf("%c", buf[i]);
}
} while (len < 64);
printf("\n");
send(clinet, "hello word!", 12, 0);
sleep(1);
close(clinet);
close(server);
return 0;
}
INADDR_ANY => "0.0.0.0"
, indicating that all connections of the machine are accepted (for example, when the machine has multiple network cards and then has multiple IPs)
Core Patterns of Client/Server Programming
- The server runs for a long time (infinite loop) to receive the client's request
- After the client connects, it sends a request (protocol data) to the server
Server-side core programming model
Programming Experiment: Client/Server Programming Experiment
- The server continuously listens for client connections
- echo client data after the server is connected
- The server disconnects after receiving quit
- The client receives user input and sends it to the server
Server
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int server = 0;
struct sockaddr_in saddr = {0};
int client = 0;
struct sockaddr_in caddr = {0};
socklen_t asize = 0;
int len = 0;
char buf[32] = {0};
int r = 0;
server = socket(PF_INET, SOCK_STREAM, 0);
if (server == -1) {
printf("server socket error\n");
return -1;
}
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.sin_port = htons(8888);
if (bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
printf("server bind error\n");
return -1;
}
if (listen(server, 1) == -1) {
printf("server listen error\n");
return -1;
}
printf("server start success\n");
while (1) {
asize = sizeof(caddr);
client = accept(server, (struct sockaddr*)&caddr, &asize);
if (client == -1) {
printf("client accept error\n");
return -1;
}
printf("client: %d\n", client);
do {
r = recv(client, buf, sizeof(buf), 0);
if (r > 0) {
printf("Receive: %s\n", buf);
if (strcmp(buf, "quit") != 0) {
len = send(client, buf, r, 0);
}
else {
break;
}
}
} while (r > 0);
close(client);
}
close(server);
return 0;
}
client
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int sock = 0;
struct sockaddr_in addr = {0};
int len = 0;
char buf[128] = {0};
char input[32] = {0};
int r = 0;
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == -1) {
printf("socket error\n");
return -1;
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.2.46");
addr.sin_port = htons(8888);
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
printf("connect error\n");
return -1;
}
printf("connect success\n");
while (1) {
printf("Input: ");
scanf("%s", input);
len = send(sock, input, strlen(input) + 1, 0);
r = recv(sock, buf, sizeof(buf), 0);
if (r > 0) {
printf("Receive: %s\n", buf);
}
else {
break;
}
}
close(sock);
return 0;
}
Thinking: How to enhance the capabilities of the server and support multiple clients at the same time?
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。