TCP

传输层协议TCP

面向连接 可靠的 字节流服务
     面向连接: 网络中的两个主机交互数据之前,必须先建立连接
     可靠的: 数据够安全的、完的传输到对方。数据不丢失 数据不出错 数据不乱序 数据不重复
     字节流服务: 数据没有发送与接收界限。发送方发送数据的次数与接收方接收数据的次数没有什么关系,如果接收端次未将数据读取完成,未读取的数据会继续保存在接缓冲区中

TCP协议的编程流程:

C/S模型 客户端服务器
     服务器:socket(创建套接字) bind(命名) listen accept(接受) recv/send(发送数据) close(关闭链接)
     客户端:socket(创建套接字) connect(建链接) send/recv(发送数据) close(关闭链接)
在这里插入图片描述
客户端和服务器端可以处在两个不同的主机上

#include <sys/types.h>
#include <sys/socket.h>
int socket (int domain, int type, int protocol); //创建 socket //套接字:通过网络发送数据
      返回值:-1 出错
                     成功返回 socket 文件描述符
      domain:协议簇 AF_INET
      type:具体协议类型
               TCP: SOCK_STREAM
               UDP: SOCK_UGRAM
      protocol: 下层具体协议 TCP/IP 默认给 0

绑定
int bind (int listenfd, struct sockaddr* seraddr, socklen_t len);
listenfd:socket 返回的文件描述符
seraddr:服务器端的 IP 地址‘
len:指定 IP 地址 的长度
      返回值:失败返回 -1,成功返回0
      失败的原因: 1、IP地址不对
                          2、端口号被占用或者没有权限使用此端口号

struct sockaddr_in
{
	sa_family  sin_family;//地址族
	u_int16_t  sin_port;//端口号:主机字节序 网络字节序
	struct in_addr  sin_addr;//IP地址:字符串形式的点分十进制---》整型值
}
struct in_addr
{
	u_int32_t s_addr;//IPV4地址,要用网络字节序表示
}
1、字节序列
主机字节序:
	大端模式:高位存低地址
	小端模式:高位存高地址
网络字节序:大端模式 
2、套接字地址:ip+端口
端口号 0 - 65535
0 - 1024	普通用户无法使用
1024 - 5000  保留
5000 以上可以使用

启动监听
int listen (int listenfd, int size);
      size:监听队列的大小
      两个队列:已完成连接的队列 +1
                        正在完成连接的队列
      size 指定内核维护的等待处理的连接队列的大小,经典的值:5

int accept (int listenfd, struct sockaddr* cli_addr, socklen_t *len)
      cli_addr:客户端的 IP 地址不用固定
      失败返回 -1
      成功返回维护本次连接的文件描述符 —>大于等于0

int recv (int fd, void *buff, size_t size, int flag); //read
      fd:客户端文件描述符
      buff:读取的数据
      size:一次性读取的数据的个数

int send (int fd, void *buff, size_t size, int flag); //write

int close (int fd);

int connect (int sockfd, struct sockaddr *ser_addr, socklen_t len);
     ser_addr:服务器的地址和端口号
     返回值:-1 连接不成功
     建立连接: sockfd 客户端的 socket 套换宇
                     ser_addr 服务端的地址信息 和哪一个服务器建立连接
                     len addr 的长度

cli

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>//字节序列转换函数所用
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>//地址转换函数所用

int main()
{
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	assert(-1!=sockfd);

	struct sockaddr_in ser;
	memset(&ser,0,sizeof(ser));
	ser.sin_family=AF_INET;
	ser.sin_port=htons(6000);
	inet_aton("127.0.0.1",(struct in_addr*)&ser.sin_addr);

	int res=connect(sockfd,(struct sockaddr*)&ser,sizeof(ser));
	assert(-1!=res);
	
	while(1)
	{
		printf("please input: ");
		fflush(stdout);
		char data[128]={0};
		fgets(data,128,stdin);
		if(strncmp(data,"bye",3)==0)
		{
			close(sockfd);
			break;
		}

		send(sockfd,data,strlen(data)+1,0);
		char buff[128]={0};
		int n=recv(sockfd,buff,127,0);
		if(n<=0)
		{
			printf("error\n");
			close(sockfd);
			break;
		}
		printf("n==%d: %s\n",n,buff);
	}
}

server

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>

int main()
{
	int listenfd=socket(AF_INET,SOCK_STREAM,0);
	assert(-1!=listenfd);

	struct sockaddr_in ser,cli;
	memset(&ser,0,sizeof(ser));//清空
	ser.sin_family=AF_INET;//IPv4地址族
	ser.sin_port=htons(6000);//主机到网络的short型,给服务器指定端口号
	ser.sin_addr.s_addr=inet_addr("127,0,0,1");//把字符型地址转换为整形

	//绑定  命名    出错:1、IP地址不正确   2、端口号被占用或者没有权限
	int res=bind(listenfd,(struct sockaddr*)&ser,sizeof(ser)); //将服务器的IP地址、端口号确定,让客户端访问
	assert(-1!=res);

	listen(listenfd,5);
	while(1)
	{
		int len=sizeof(cli);
		//c特定客户端和服务器连接的文件描述符
		//accept函数只有在有客户端连接的情况下返回
		int c=accept(listenfd,(struct sockaddr*)&cli,&len);//阻塞运行
		assert(-1!=c);

		while(1)
		{
			char buff[128]={0};
			int n=recv(c,buff,127,0);//阻塞  有数据可读或者客户端退出都会返回
			if(n==0)
			{
				printf("client unlink\n");
				close(c);
				break;//要继续接收下一个连接
			}
			else if(n==-1)
			{
				printf("error\n");
				close(c);
				break;
			}

			printf("n==%d: %s",n,buff);

			send(c,"OK",2,0);
		}
	}
	close(listenfd);
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值