协议栈:实现协议的代码叫做协议栈。
网络理论介绍一般采用OSI模型,Linux中网络栈的介绍一般分为四层的Internet模型
OSI七层网络模型:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层
Linux TCP/IP模型:应用层 传输层, 网际层,网络接口
TCP/UDP
TCP/UDP的区别:
TCP:为应用层提供可靠的、面向连接的、基于流(一个字节一个字节发送)的服务。TCP协议使用超时重传、数据确认等方式来确保数据包被
正确发送到目的地,因此可靠的。
所谓三次握手是指TCP连接时,需要客户端和服务器总共发送3个包。
四次挥手,断开连接的时候。
UDP:与TCP相反,不可靠,无连接,基于数据报的服务。在发送的过程中出现错误时,只会简单的通知应用层发送失败
因此shiyongUDP需要自己处理数据确认,超时重传。
socket(套接字)
服务器搭建步骤及相关函数:
服务器 客户端
创建socket 创建socket
绑定信息bind(将自己的IP等信息公布) 发起连接(connect)
设置监听队列 listen 读写recv、send(实现信息的收发)
接受连接accept
读写recv/send
服务器端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
void *ClientHandler(void *arg)
{
int fd = *(int *)arg;
char buf[32] = {0};
pthread_detach(pthread_self());//获取自己的线程号, 释放自己
while(1)
{
//从fd接收消息, TCP连接相当一个文件,fd是文件描述符,从fd读取,就是接收客户端消息
int ret = recv(fd, buf, sizeof(buf), 0);
if (-1 == ret)
{
perror("recv");
exit(1);
}
else if(0 == ret)
{
break;
}
if(!strcmp(buf, "bye"))
{
break;
}
printf("%s\n", buf);
memset(buf, 0, sizeof(buf));
}
close(fd);
printf("%d client leave\n", fd);
}
int main()
{
//创建socket
int sockfd = socket(AF_INET,SOCK_STREAM,0); //ipv4 流式套接字 集体的协议类型
if (-1 == sockfd)
{
perror("socket");
exit(1);
}
int opt = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));//使地址可重复绑定
struct sockaddr_in server_addr; //用于保存服务器的信息
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = 8000;
server_addr.sin_addr.s_addr = inet_addr("192.168.122.2");
//绑定信息
int ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (-1 == ret)
{
perror("bind");
exit(1);
}
//监听队列
ret = listen(sockfd, 10);
if (-1 == ret)
{
perror("listen");
exit(1);
}
struct sockaddr_in client_addr; //用于保存客户端的信息
int length = sizeof(client_addr);
while(1)
{
//接收连接(建立TCP连接)
int fd = accept(sockfd, (struct sockaddr *)&client_addr, &length);//阻塞态
if (-1 == fd)
{
perror("accept");
exit(1);
}
printf("recive from client %d\n", fd);
pthread_t tid;
ret = pthread_create(&tid, NULL, ClientHandler, &fd);
if (ret != 0)
{
perror("recv");
exit(1);
}
usleep(10000);
}
close(sockfd);
return 0;
}
客户端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
//创建socket
int sockfd = socket(AF_INET,SOCK_STREAM,0); //ipv4 流式套接字 集体的协议类型
if (-1 == sockfd)
{
perror("socket");
exit(1);
}
struct sockaddr_in server_addr; //用于保存服务器的信息
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = 8000;
server_addr.sin_addr.s_addr = inet_addr("192.168.122.2");
//向服务器发起连接
int ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (-1 == ret)
{
perror("connect");
exit(1);
}
char buf[32] = {0};
while(1)
{
scanf("%s", buf);
ret = send(sockfd, buf, strlen(buf), 0);
if (-1 == ret)
{
perror("send");
exit(1);
}
if(!strcmp(buf, "bye"))
{
break;
}
printf("%s\n", buf);
memset(buf, 0, sizeof(buf));
}
close(sockfd);
return 0;
}