1. TCP/IP理论基础
Linux的优点之一就是在于它丰富而稳定的网络协议栈,其范围是从协议无关层(如通用的socket层接口和设备层)到各种网络协议的实现。
对于网络理论介绍一般采用OSI模型,但是Linux中网络栈的介绍一般分为四层的Internet模型。
TCP/IP 实际上一个协同工作的通信家族,为网络数据通信提供通路。为讨论方便可TCP/IP 协议组大体上分为三部分:
1、Internet 协议(IP)
2、传输控制协议(TCP)和用户数据报协议(UDP)
3、处于 TCP 和 UDP 之上的一组应用协议。它们包括:TELNET,文件传送协议(FTP),域名服务(DNS)和简单的邮件传送程序(SMTP)等。
第一部分称为网络层。主要包括Internet 协议(IP)、网际控制报文协议(ICMP)和地址解析协议(ARP)
Internet 协议(IP)
该协议被设计成互联分组交换通信网,以形成一个网际通信环境。它负责在源主机和目的地主机之间传输来自其较高层软件的称为数据报文的数据块,它在源和目的地之间提供非连接型传递服务。
网际控制报文协议(ICMP)
它实际上不是IP层部分,但直接同IP层一起工作,报告网络上的某些出错情况。允许网际路由器传输差错信息或测试报文。
地址解析协议(ARP)
ARP 实际上不是网络层部分,它处于IP和数据链路层之间,它是在32位IP地址和48位物理地址之间执行翻译的协议。
第二部分是传输层协议,包括传输控制协议和用户数据报文协议
传输控制协议(TCP):
该协议对建立网络上用户进程之间的对话负责,它确保进程之间的可靠通信,所提供的功能如下:
1.监听输入对话建立请求
2.请求另一网络站点对话
3.可靠的发送和接收数据
4.适度的关闭对话
用户数据报文协议(UDP):
UDP 提供不可靠的非连接型传输层服务,它允许在源和目的地之间传送数据,而不必在传送数据之前建立对话。它主要用于那些非连接型的应用程序,如:视频点播
这部分主要包括Telnet,文件传送协议(FTP 和TFTP),简单文件传送协议(SMTP)和域名服务(DNS)等协议
IP主要有以下四个主要功能:
数据传送
寻址
路由选择
数据报文的分段
IP的主要目的是为数据输入/输出网络提供基本算法,为高层协议提供无连接的传送服务.这意味着在IP将数据递交给接收站点以前不在传输站点和接收站点之间建立对话。它
只是封装和传递数据,但不向发送者或接收者报告包的状态,不处理所遇到的故障。
2. 代码实现
服务器:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#define PORT 8888
int main()
{
int sockfd, ret, fd;
char buf[100] = {0};
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
printf("Start Server\n");
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(-1 == sockfd)
{
perror("socket");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = PORT;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(-1 == ret)
{
perror("bind");
exit(1);
}
printf("Lintening...\n");
ret = listen(sockfd, 5);
if(-1 == ret)
{
perror("listen");
exit(1);
}
int length = sizeof(client_addr);
fd = accept(sockfd, (struct sockaddr *)&client_addr, &length);
if(-1 == fd)
{
perror("accept");
exit(1);
}
printf("Accept %d, Port %d\n", fd, client_addr.sin_port);
while(1)
{
ret = recv(fd, buf, sizeof(buf), 0);
if(-1 == ret)
{
perror("recv");
exit(1);
}
if(!strcmp(buf, "bye"))
{
break;
}
printf("Recv From Client: %s\n", buf);
memset(buf, 0, sizeof(buf));
}
close(fd);
close(sockfd);
return 0;
}
客户端:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#define PORT 8888
int main()
{
int sockfd, ret;
struct sockaddr_in server_addr;
char buf[100] = {0};
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(-1 == sockfd)
{
perror("socket");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = PORT;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
printf("Start connecting...\n");
ret = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(-1 == ret)
{
perror("connect");
exit(1);
}
while(1)
{
scanf("%s", buf);
ret = send(sockfd, buf, strlen(buf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
if(!strcmp(buf, "bye"))
{
break;
}
memset(buf, 0, sizeof(buf));
}
close(sockfd);
return 0;
}