c网络编程

First Post:

Last Update:

Word Count:
1.1k

Read Time:
6 min

C Network programing

字节序

验证当前电脑是大端还是小端。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

void byteorder() {
union {
short value;
char union_bytes[sizeof(short)];
} test;
test.value = 0x0102;
if((1 == test.union_bytes[0]) && (2 == test.union_bytes[1])) {
printf("big endian\n");
}else if((2 == test.union_bytes[0]) && (1 == test.union_bytes[1])) {
printf("little endian\n");
}else {
printf("unknown\n");
}
}

int main(void) {
byteorder();
return 0;
}

测试listen函数

server.c

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
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

static bool stop = false;
static void handle_term(int sig) {
stop = true;
}

int main(int argc, char **argv) {
signal(SIGTERM, handle_term);
if(argc <= 3) {
printf("Usage: %s ip_address port_number backlog\n", basename(argv[0]));
return 1;
}
const char *ip = argv[1];
int port = atoi(argv[2]);
int backlog = atoi(argv[3]);

int sock = socket(PF_INET, SOCK_STREAM, 0);
assert(sock >= 0);
struct sockaddr_in address;
bzero(&address, sizeof(address)); //清空为0
address.sin_family = AF_INET;

//inet_pton是一个IP地址转换函数,
//可以在将IP地址在“点分十进制”和“二进制整数”之间转换
//而且inet_pton和inet_ntop这2个函数能够处理ipv4和ipv6

inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port); //转化为网络字节序

//绑定
int ret = bind(sock, (struct sockaddr *)&address, sizeof(address));
assert(-1 != ret);

ret = listen(sock, backlog);
assert(-1 != ret);

//通过系统发送信号来终止程序
while(!stop) {
sleep(1);
}

close(sock);
printf("End program\n");

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
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char **argv) {
if(argc <= 2) {
printf("Usage: %s [ip] [port]\n", basename(argv[0]));
return 1;
}

const char *ip = argv[1];
int port = atoi(argv[2]);

struct sockaddr_in address;
bzero(&address, sizeof(address));

address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);

int sock = socket(PF_INET, SOCK_STREAM, 0);
assert(sock >= 0);

int ret = bind(sock, (struct sockaddr *)&address, sizeof(address));
if(-1 == ret) {
perror("bind");
return 1;
}

ret = listen(sock, 5);
assert(ret != -1);

struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int c_fd = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len);
if(c_fd == -1) {
perror("accept::");
}else {
char remote[INET_ADDRSTRLEN];
printf("connected with ip: %s and port %d\n",
inet_ntop(AF_INET, &client_addr.sin_addr, remote, INET_ADDRSTRLEN),
ntohs(client_addr.sin_port));

close(c_fd);
}

return 0;
}

Echo Server例子

客户端

client.cpp

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
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

using namespace std;
#define SERVER_PORT 6666
#define SERVER_IP "127.0.0.1"

int main(int argc, char **argv) {
int sockfd;
int n;
struct sockaddr_in serveraddr;
char str[256] = "Hello You guys\n";
if(argc < 2) {
cout << "Usage: ./clinet [message]" << endl;
fputs("Input error! \n", stderr);
exit(1);
}

sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serveraddr, 0, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;

inet_pton(AF_INET, SERVER_IP, &serveraddr.sin_addr);
serveraddr.sin_port = htons(SERVER_PORT); //转化为网络字节顺序

connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
write(sockfd, argv[1], strlen(argv[1]));
n = read(sockfd, str, sizeof(str) - 1);
if(n > 0) {
str[n] = '\0';
cout << str;
}else {
perror("error");
}

cout << endl << "finished" << endl;
close(sockfd);
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
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>

#define SERVER_PORT 6666
int main(void) {
int sock; //信箱
//AF_INET表示使用网络地址, SOCK_STREAM表示使用TCP协议
sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_addr; //这个结构体,头文件中已经声明
//清空标签
bzero(&server_addr, sizeof(server_addr));
//设置协议家族为网络协议
//htonl = host to net ,选择协议族为ipv4,
server_addr.sin_family = AF_INET;
//监听本地所有地址
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(SERVER_PORT); //绑定端口号
//实现标签贴到信箱上
bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));

listen(sock, 128); //同时的连接数量,同时来的信件接受多少封,这里为128

//万事俱备,只等来信.
printf("等待客户连接...\n");

while(1) {
struct sockaddr_in client;
int client_sock ; //客户端
char client_ip[64];
char buf[256];
int buf_len;
socklen_t client_addr_len = sizeof(client);

client_sock = accept(sock, (struct sockaddr *)&client, &client_addr_len);
//打印客户端地址和端口号
//转化网络字节序
printf("client ip: %s\n port: %d\n",
inet_ntop(AF_INET, &client.sin_addr.s_addr, client_ip, sizeof(client_ip)),
ntohs(client.sin_port));

//读取数据
buf_len = read(client_sock, buf, sizeof(buf) - 1);
buf[buf_len] = '\x00';
printf("接受到消息: %s\n", buf);
for(int i = 0; i < buf_len; i++) {
buf[i] = toupper(buf[i]);
}
write(client_sock, buf, strlen(buf));
printf("write[%s] finished!!!\n", buf);

close(client_sock);
}

return 0;
}

打赏点小钱
支付宝 | Alipay
微信 | WeChat