linux下socket通信demo,server和client
C语言中文网的socket教程,一系列,非常棒,不过有些章节要收费。 http://c.biancheng.net/socket/
一篇博客,单个的socket client和server的通信,代码很好,我修改了一小部分,并加上了注释,如下。 https://www.cnblogs.com/zkfopen/p/9441264.html
# server.cpp
//server.cpp
#include<stdlib.h> //这5个是unix常用库,加了不会错,不加很可能会出错。
#include<unistd.h>
#include<string.h> //memset() 等
#include<stdio.h> //printf
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h> //socekt通信,这3个都要
#include<netinet/in.h> //定义了sockaddr_in
#include<arpa/inet.h> //包含inet_addr("127.0.0.1")
#define MAXSIZE 4096
int main(int argc, char** argv){
//AF_INET,表示ipv4,还有AF_INET6; AF意思是Address Family
//SOCK_STREAM表示TCP,还有 SOCK_DGRAM:UDP
//socket函数第三个参数,0,表示传输协议。它有三种取值,IPPROTO_TCP,IPPROTO_UDP,0。 0表示根据第二个参数自动推演,所以一般就用0
int server_sock;
if( (server_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
printf("create socket error: %s\n", strerror(errno));
return 0;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));//把addr的内存初始化为0。这句相当于是快速的初始化。
addr.sin_family = AF_INET;//ipv4
// addr.sin_addr.s_addr = htonl(INADDR_ANY);// 0.0.0.0, 监听所有网卡的所有ip地址。 htonl host to network long,把host字节序转换为网路字节序,long
addr.sin_addr.s_addr = inet_addr("0.0.0.0");// 0.0.0.0, 监听所有网卡的所有ip地址。
addr.sin_port = htons(6666);//host to network short.
// bind 绑定成功,返回0,失败返回-1
int bind_ret = bind(server_sock, (struct sockaddr*)&addr, sizeof(addr));
if(-1 == bind_ret){//addr类型是sockaddr_in,这里要给它转成sockaddr
printf("bind socket error: %s\n", strerror(errno));
return 0;
}
int listen_ret = listen(server_sock, 10);
if(-1 == listen_ret){//10是请求队列的长度。并发量小可以设置成10或20。
printf("listen socket error: %s\n", strerror(errno));
return 0;
}
printf("======waiting for client's request======\n");
int client_sock, n;
char buff[4096];
while(1){
//接受客户端socket连接
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &len);
//如果不关心客户端的地址,也可以这样:accept(server_sock, NULL, NULL);
if( -1 == client_sock){
printf("accept socket error");
continue;
}
//接收数据
n = recv(client_sock, buff, MAXSIZE-1, 0);//MAXSIZE是接收数据的长度,第4个参数一般配置为0
buff[n] = '\0';
printf("recv msg from client: %s\n", buff);
close(client_sock);
}
close(server_sock);
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
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
# client.cpp
//client.cpp
#include<stdio.h> //这4个是unix下的常用库
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h> //包含inet_addr("127.0.0.1")
#define MAXSIZE 4096
int main(int argc, char** argv){
char recvline[4096], sendline[4096];
//运行时输入ip地址作为参数,
// if( argc != 2){
// printf("usage: ./client <ipaddress>\n");
// return 0;
// }
int sock_client = socket(AF_INET, SOCK_STREAM, 0);
if( sock_client < 0){
printf("create socket error: %s\n", strerror(errno));
return 0;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(6666);
//addr.sin_addr.s_addr = inet_addr(argv[1]);//将main传入的参数赋给addr.sin_addr
addr.sin_addr.s_addr = inet_addr("127.0.0.1");//将main传入的参数赋给addr.sin_addr
//也可以用下面的方法传,这个方法的好处是能检测输入是否正确,另外inet_pton这个函数ipv6也可以处理。
// if( inet_pton(AF_INET, argv[1], &addr.sin_addr) <= 0){
// // inet_pton 将点分十进制串转换成网络字节序二进制值,此函数对IPv4地址和IPv6地址都能处理。
// printf("inet_pton error for %s\n",argv[1]);
// return 0;
// }
int connect_ret = connect(sock_client, (struct sockaddr*)&addr, sizeof(addr));
if(connect_ret < 0){
printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
return 0;
}
printf("send msg to server: \n");
fgets(sendline, 4096, stdin);
if(send(sock_client, sendline, strlen(sendline), 0) < 0){
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
return 0;
}
// close(sock_client);
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
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
# struct sockaddr和struct sockaddr_in的区别和用法
https://blog.csdn.net/slvher/article/details/8856003
//sockaddr_in的结构
struct sockaddr_in {
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
编辑 (opens new window)
上次更新: 2023/05/07, 17:27:54