socket编程

socket编程

1.什么是socket?

socket是应用层与TCP/IP协议簇通信的中间抽象层,就是对网络中不同主机的应用进程之间进行双向通信的端点的抽象,提供了应用层进程利用网络协议交换数据的机制。套接字上联应用层,下联协议栈,是应用程序利用网络协议进行通信的接口。

2.socket分类

  • SOCK_STREAM

    基于TCP协议,面向连接,提供可靠传输、拥塞控制、数据校验、数据重传。

  • SOCK_DGRAM

    尽最大努力交付,可以一对多通信,多对多通信。

  • SOCK_RAM

    基于ip协议,可以基于ip协议自行组装数据包,利用原始套接字可以处理如ICMP、IGMP等网络层的数据包。

3.常用的api

1
2
3
4
5
6
7
8
int socket(int domain,int type,int protocol)                    //用于创建一个socket
int bind(int fd,const struct sockaddr *addr,socklen_t len) //用于绑定一个端口
int listen(int fd,int backlog); //用于监听即将到来的连接
int connect(int fd,const struct sockaddr *addr,socklen_t len) //用于连接一个远程服务器
ssize_t send(int fd,const void *buf,size_t len,int flags) //类似于write函数
ssize_t recv(int sockfd,void *buf,size_t len,int flags) //类似于read函数
ssize_t sendto(int sockfd,const void *buf,size_t len,int flags,const struct sockaddr *dest_addr,socklen_t addrlen); //用于udp socket编程发送数据
ssize_t recvfrom(int sockfd,void *buf,size_t len,int flags,const struct sockaddr *src_addr,socklen_t *addrlen); //用于udp socket编程接收数据

4.基本的编程步骤

服务端

graph TD;
a(socket 创建socket文件)-->b(bind 绑定端口和ip地址)-->c(listen 开始监听ip和端口)-->d(accept 接收来自客户端的连接)-->e(read/write开始和客户端收发数据)

客户端

graph TD;
a(socket 创建socket文件)-->b(connect 连接服务器)-->c(read/write,开始和服务端收发数据)

5.实例

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
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <unistd.h>
#define SOCKLEN (sizeof(struct sockaddr))
void Usage(char* argv)
{
printf("Usage:\n");
printf("%s SERVERADDR SERVERPORT", argv);
}
int New_Socket(char* addr, char* port, int backlog)
{
//创建socket
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in ADDR;
ADDR.sin_family = AF_INET;
ADDR.sin_port = htons(atoi(port));
if (inet_pton(AF_INET, addr, &ADDR.sin_addr) != 1) {
perror("inet_pton");
}
//绑定地址以及端口
if (bind(fd, (struct sockaddr*)&ADDR, SOCKLEN) != 0) {
perror("bind");
}
//进入监听状态,等待接收来之客户端的连接
if (listen(fd, backlog) != 0) {
perror("listen");
}
//返回socket
return fd;
}
int main(int argc, char** argv)
{
socklen_t len = sizeof(struct sockaddr_in);
if (argc != 3) {
Usage(argv[0]);
exit(0);
}
int fd = New_Socket(argv[1], argv[2], 5);
//定义客户端信息变量
struct sockaddr_in client_addr;
//接收来自客户端发来的请求
int clientfd = accept(fd, (struct sockaddr*)&client_addr, &len);
if (clientfd == -1) {
perror("accept");
exit(0);
}
char buffer[100];
bzero(buffer, 100);
//接收来自客户端发来的数据
if (read(clientfd, buffer, 100) > 0) {
printf("recv from client:%s", buffer);
} else {
perror("read");
}
}
2.客户端
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
//客户端
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define SOCKLEN (sizeof(struct sockaddr))
void Usage(char* argv) //使用帮助函数
{
printf("Usage:\n");
printf("%s SERVERADDR SERVERPORT", argv);
}
int New_Socket(char* addr, char* port) //创建socket用于连接远程服务器
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
perror("socket");
return -1;
}
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(port));
//转换ip地址类型
if (inet_pton(AF_INET, addr, &serveraddr.sin_addr) != 1) {
perror("inet_pton");
return -1;
}
//连接服务器
if (connect(fd, (struct sockaddr*)&serveraddr, SOCKLEN) != 0) {
perror("connect");
return -1;
}
return fd;
}
int main(int argc, char** argv)
{
if (argc != 3) {
Usage(argv[0]);
return 0;
}
//创建socket
int fd = New_Socket(argv[1], argv[2]);
if (fd == -1) {
printf("connect server error!\n");
return 0;
}
//定义发送数据
char* str = "Hello,World";
unsigned int len = strlen(str) + 1;
//将数据写入socket发送缓冲区
if (write(fd, str, len) != len) {
printf("send string to server error!\n");
return 0;
}
printf("send string to server successful!\n");
return 0;
}


socket编程
https://dreamaccount.github.io/2022/04/17/socket编程/
作者
404NotFound
发布于
2022年4月17日
许可协议