1、套接字概述
套接字的本意是插座,在网络中用来描述计算机中不同程序与其他计算机程序的通信方式。
常用的套接字类型有3种:
1)流套接字(SOCK——STREAM):使用了面向连接的可靠的数据通信方式,即TCP套接字;
2)数据报套接字(Raw Sockets):使用了不面向连接的数据传输方式,即UDP套接字;
3)原始套接字(SOCK——RAW):没有经过处理的IP数据包,可以根据自己程序的要求进行封装。
2、常用函数
1、创建套接字函数:成功时返回文件描述符,失败时返回-1
int socket(int domain,int type,int protocol);
2、在指定套接字上创建链接函数:成功时返回0,失败时返回-1
int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen);
3、将一个套接字和某个端口绑定在一起的函数:成功时返回0,失败时返回-1
int bind(int sockfd,struct sockaddr *my_addr,socklen_t addrlen);
4、把套接字转化为被动监听函数:成功时返回0,失败时返回-1
int listen(int s,int backlog);
5、接收连接请求函数:成功时返回文件描述符,失败时返回-1
int accept(int s,struct sockaddr *addr,socklen_t *addrlen); //参数s是由函数socket创建,经函数bind绑定到本地某一端口上,然后通过
//函数listen转化而来的监听套接字
//参数addr用来保存发起连接请求的主机的地址和端口
//参数addrlen是addr所指向的结构体的大小
6、在TCP套接字上发送数据函数:有连接
包含3要素:套接字s,待发数据msg,数据长度len
ssize_t send(int s,const void *msg,size_t len,int flags);
7、在TCP套接字上接收数据函数:有连接
包含3要素:套接字s,接收缓冲区buf,长度len
ssize_t recv(int s,void *buf,size_t len,int flags);
8、在UCP套接字上发送数据函数:无连接
ssize_t sendto(int s,const void *msg,size_t len,int flags,const struct sockaddr *to,socklen_t tolen);
9、在UDP套接字上接收数据函数:无连接
ssize_t recvfrom(int s ,void *buf,size_t len,int flags,struct sockaddr *from,socklen_t *fromlen);
10、关闭套接字函数:
int close(int fd);
11、多路复用函数:
int select(int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);
3、服务器端套接字(接收连接请求的套接字)创建过程
第一步:调用socket函数创建套接字。
第二步:调用bind函数分配IP地址和端口号。
第三部:调用listen函数转为可接收请求状态。
第四步:调用accept函数受理连接请求。
4、客户端套接字(发送连接请求的套接字)创建过程
只有两步:
1、调用socket函数创建套接字。
2、调用connect函数向服务器端发送连接请求。
5、Linux的文件操作
文件描述符:是系统自动分配给文件或套接字的整数。
每当生成文件或套接字,操作系统就会自动返回给我们一个整数。这个整数就是文件描述符,即创建的文件或套接字的别名,方便称呼而已。文件描述符在Windows中又称为句柄。
1、打开文件:
2、关闭文件或套接字:
3、将数据写入文件:
4、读取文件中的数据:
注:ssize_t = signed int, size_t = unsigned int,都是通过typedef声明,为基本数据类型取的别名。既然已经有了基本数据类型,那么为什么还需要为它取别名呢?是因为目前普遍认为int是32位的,而过去16位操作系统时代,int是16位的。根据系统的不同,时代的变化,基本数据类型的表现形式也随着变化的。如果为基本数据类型取了别名,以后要修改,也就只需要修改typedef声明即可,这将大大减少代码变动。
6、服务器端实例
服务器端受理连接请求的程序。编译并运行该程序,创建等待连接请求的服务器端。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> void error_handling(char *message); int main(int argc, const char * argv[])
{ int serv_sock; int clnt_sock; struct sockaddr_in serv_addr; struct sockaddr_in clnt_addr;
socklen_t clnt_addr_size; char message[] = "Hello World!"; if(argc != 2)
{ printf("Usage:%s <port>\n", argv[0]); exit(1);
} serv_sock = socket(PF_INET, SOCK_STREAM, 0); if(serv_sock == -1)
error_handling("socket() error"); memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
error_handling("bind() error"); if(listen(serv_sock, 5) == -1)
error_handling("listen() error");
clnt_addr_size = sizeof(clnt_addr); clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_size); if(clnt_sock == -1)
error_handling("accept() error"); write(clnt_sock, message, sizeof(message));
close(clnt_sock); close(serv_sock); return 0;
} void error_handling(char *message)
{ fputs(message, stderr);
fputc('\n', stderr); exit(1);
}
-
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
-
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
7、客户端实例
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> void error_handling(char *message); int main(int argc, const char * argv[])
{ int sock; struct sockaddr_in serv_addr; char message[30]; int str_len; if(argc != 3)
{ printf("Usage: %s <IP> <port>\n", argv[0]); exit(1);
} sock = socket(PF_INET, SOCK_STREAM, 0); if(sock == -1)
error_handling("socket() error"); memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
serv_addr.sin_port = htons(atoi(argv[2])); if(connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
error_handling("connect() error"); str_len = read(sock, message, sizeof(message) - 1); if(str_len == -1)
error_handling("read() error"); printf("Message from server: %s \n", message);
close(sock); return 0;
} void error_handling(char *message)
{ fputs(message, stderr);
fputc('\n', stderr); exit(1);
}
-
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
-
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
参考:《TCP/IP网络编程》
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31343455/viewspace-2108013/
,如需转载,请注明出处,否则将追究法律责任。