1、socket编程html
网络功能是Uinux/Linux的一个重要特色,有着悠久的历史,所以有一个很是固定的编程套路。编程
基于TCP的网络编程:服务器
基于链接, 在交互过程当中, 服务器和客户端要保持链接, 不能断开。重发一切出错数据、数据验证, 保证数据的正确性、完整性和顺序性,网络
缺点是消耗的资源比较大。数据结构
基于UDP的网络编程:dom
无链接协议, 在网络交互过程当中不保持链接, 只须要在发送数据时链接一下, 不重发、验证数据。优势是资源消耗少, 数据的可靠性完整性socket
顺序性得不到保证。函数
2、编程步骤:server
服务器:htm
① 建立socket(套接字) socket()
② 准备通讯地址
③ 将建立的socket和通讯地址绑定 bind()
④ 监听端口 listen()
⑤ 等待客户端链接 accpet()
⑥ 通讯双方收发数据 read()/write()
send()/recv()
⑦ 关闭socket
客户端:
① 建立socket(套接字) socket()
② 准备通讯地址
③ 链接服务器 connect()
④ 收发数据 read()/write()
send()/recv()
⑤ 关闭socket
3、API详解
① socket()函数
int socket(domain, type, protocol)
domain:
AF_UNIX/AF_LOCAL/AF_FILE: 本地通讯
AF_INET: 网络通讯 ipv4
AF_INET6: 网络通讯 ipv6
注:若是AF换成PF效果同样
type, 选择通讯类型, 主要包括:
SOCK_STREAM: TCP
SOCK_DGRAM : UDP
protocol, 原本应该指定通讯协议, 但如今基本废弃, 由于协议已经在前面两个参数指定完成,给0便可
② bind()函数
int bind(int sockfd, struct sockaddr *addr, size)
sockfd: 要绑定的套接字描述符
size: 第二个参数占据的内存空间大小
addr: 涉及三个数据结构struct sockaddr, sockaddr_un, sockaddr_in
sockaddr, 主要用于函数参数, 不负责存储数据
sockaddr_un, 当着本地通讯时, 用于本地通讯使用的地址 (sys/un.h)
sockaddr_in, 当着网络通讯时, 负责存储网络通讯的地址数据
struct sockaddr_in {
sin_family; //用于指定协议族, 和socket()的参数保持一致
sin_port; //网络通讯使用的端口号
sin_addr; //存储网络通讯的ip地址
}
③ htons
④ inet_aton
⑤ listen()函数
int listen(int sockfd, int backlog)
sockfd: 将sockfd参数所标识的套接字为被动模式, 使之能够接受链接请求
backlog: 表示未决链接请求队列的最大长度, 即容许最多有多少个未决链接请求存在。若服务器的未决链接请求已达到该值, 则客户端经过 connect()链接服务器的操做将返回-1,且error为ECONNREFUSED
⑥ accpet()函数
int accpet(sockfd, struct sockaddr* addr, socklen_t *addrlen)
从sockfd参数所标识套接字对应未决链接请求队列中取出的一个链接请求, 同时建立一个新的套接字,用于该链接通讯, 返回套接字的描述符
addr和addrlen 用于输出链接请求发起者的地址信息
返回值: 为新建立用于和客户端通讯的套接字描述符 失败-1, error
⑦ inet_ntoa
⑧ recv()函数
int recv(int sockfd, buf, len, flags)
flags, 一般取0: 阻塞收取数据
O_NONBLOCK: 不阻塞, 若是未收到数据, 返回错误信息
返回值:
>0, 实际接受数据字节数
-1 , 出错, error
0 , 通讯的另外一端关闭
⑨ send()函数
int send(int sockfd, buf, len, flags)
flags: 一般取0, 阻塞发送
O_NONBLOCK: 不阻塞, 若是未收到数据, 返回错误信息
⑩ connect()函数
int connect(int sockfd, addr, addr_len)
参数参考bind()
4、TCP示例
复制代码
1 /*******************************
2 client.c
3 ********************************/
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <sys/socket.h>
10 #include <netinet/in.h>
11 #include <arpa/inet.h>
12 #define PORT 8888
13
14 int main()
15 {
16 /*1 建立socket*/
17 int sockfd = socket(AF_INET, SOCK_STREAM, 0);
18 if(sockfd == -1)
19 {
20 perror("socket failed");
21 exit(-1);
22 }
23 /*2 准备通讯地址*/
24 struct sockaddr_in addr;
25 addr.sin_family = AF_INET;
26 /*设置为服务器进程的端口号*/
27 addr.sin_port = htons(PORT);
28 /*服务器所在主机IP地址*/
29 inet_aton("192.168.182.10", &addr.sin_addr);
30
31 /*3 链接服务器*/
32 int res = connect(sockfd,
33 (struct sockaddr *)&addr,
34 sizeof(addr));
35 if(res == -1)
36 {
37 perror("connect failed");
38 exit(-1);
39 }
40 printf("链接服务器成功....\n");
41 /*4 和服务器交换数据*/
42 char buf[100] = {0};
43 char *str = "借点钱能够吗...";
44 write(sockfd, str, strlen(str)) ;
45 read(sockfd, buf, sizeof(buf));
46 printf("服务器说:%s\n", buf);
47
48 /*关闭链接*/
49 close(sockfd);
50 return 0;
51 }
复制代码
复制代码
1 /************************************
2 server.c
3 *************************************/
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13 #define PORT 8888
14
15 int main()
16 {
17 /*1 建立socket*/
18 int sockfd = socket(AF_INET, SOCK_STREAM, 0);
19 if(sockfd == -1)
20 {
21 perror("socket failed");
22 exit(-1);
23 }
24 /*2 准备通讯地址*/
25 struct sockaddr_in addr;
26 addr.sin_family = AF_INET;
27 addr.sin_port = htons(PORT);
28 inet_aton("192.168.182.10", &addr.sin_addr);
29
30 /*3 绑定socket和通讯地址*/
31 int res = bind(sockfd,(struct sockaddr *)&addr,
32 sizeof(addr));
33 if(res == -1)
34 {
35 perror("bind failed");
36 exit(-1);
37 }
38 /*4 监听端口*/
39 res = listen(sockfd, 100);
40 if(res == -1)
41 {
42 perror("listen failed");
43 exit(-1);
44 }
45 printf("开始监听%d端口,等待客户端链接...\n",
46 PORT);
47 /*5 处理接收客户端的链接请求*/
48 //用于保存客户端地址信息
49 struct sockaddr_in fromaddr;
50 /*len 取0会是什么效果?*/
51 socklen_t len = sizeof(fromaddr);
52 int clientfd = accept(sockfd,
53 (struct sockaddr *)&fromaddr,
54 &len);
55 if(clientfd == -1)
56 {
57 perror("accept failed");
58 exit(-1);
59 }
60 printf("有一个客户端链接到服务器,它是:%s\n",
61 inet_ntoa(fromaddr.sin_addr));
62 /*6 处理客户端数据*/
63 char buf[100] = {0};
64 int count = recv(clientfd, buf, sizeof(buf),0);
65 printf("从客户端读取到%d字节:%s\n",
66 count, buf);
67 char *str = "欢迎你客户端";
68 send(clientfd, str, strlen(str), 0);
69 /*关闭链接*/
70 close(clientfd);
71 close(sockfd);
72 return 0;
73 }
复制代码
5、UDP示例
复制代码
1 /********************************
2 UDP_client.c
3 *********************************/
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <sys/socket.h>
10 #include <netinet/in.h>
11 #include <arpa/inet.h>
12
13 #define PORT 12345
14 int main()
15 {
16 /*1 建立socket*/
17 int sd = socket(PF_INET, SOCK_DGRAM, 0);
18 if(sd == -1)
19 {
20 perror("socket failed");
21 exit(-1);
22 }
23 /*2 准备地址*/
24 struct sockaddr_in addr;
25 addr.sin_family = PF_INET;
26 addr.sin_port = htons(PORT);
27 inet_aton("192.168.182.10", &addr.sin_addr);
28 /*3 进行通讯*/
29 char *str = "借点钱能够吗";
30 sendto(sd, str, strlen(str), 0,
31 (struct sockaddr *)&addr,
32 sizeof(addr));
33 char buf[100] = {0};
34 int len = sizeof(addr);
35 recvfrom(sd, buf, sizeof(buf), 0,
36 (struct sockaddr *) &addr,
37 &len);
38 printf("服务器说:%s\n", buf);
39 close(sd);
40 }
复制代码
复制代码
1 /********************************
2 UDP_server.c
3 *********************************/
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <sys/socket.h>
10 #include <netinet/in.h>
11 #include <arpa/inet.h>
12
13 #define PORT 12345
14 int main()
15 {
16 /*1 建立socket*/
17 int sd = socket(PF_INET, SOCK_DGRAM, 0);
18 if(sd == -1)
19 {
20 perror("socket failed");
21 exit(-1);
22 }
23 /*2 准备地址*/
24 struct sockaddr_in addr;
25 addr.sin_family = PF_INET;
26 addr.sin_port = htons(PORT);
27 inet_aton("192.168.182.10", &addr.sin_addr);
28 /*3 socket addr 绑定*/
29 int res = bind(sd, (struct sockaddr *)&addr,
30 sizeof(addr));
31 if(res == -1)
32 {
33 perror("bind failed");
34 exit(-1);
35 }
36 /*4 进行通讯*/
37 while(1)
38 {
39 char buf[100] = {0};
40 struct sockaddr_in fromaddr;
41 int len = sizeof(fromaddr);
42 recvfrom(sd, buf, sizeof(buf), 0,
43 (struct sockaddr *) &fromaddr,
44 &len);
45 printf("从客户端%s接收到数据:%s\n",
46 inet_ntoa(fromaddr.sin_addr),
47 buf);
48 char *str = "没问题,借多少";
49 sendto(sd, str, strlen(str), 0,
50 (struct sockaddr *)&fromaddr,
51 sizeof(fromaddr));
52 }
53 close(sd);
54
55 }
http://www.cnblogs.com/jiangson/p/5977601.html