Linux下网络通信TCP/IP

协议栈:实现协议的代码叫做协议栈。

网络理论介绍一般采用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;
}

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页