C/S模型的TCP通信分析

TCP通信流程分析

client:

  1. socket() 创建socket
  2. connect(); 与服务器建立连接
  3. write() 写数据到 socket
  4. read() 读转换后的数据。
  5. 显示读取结果
  6. close()

server:

  1. socket() 创建socket
  2. bind() 绑定服务器地址结构
  3. listen() 设置监听上限
  4. accept() 阻塞监听客户端连接
  5. read(fd) 读socket获取客户端数据
  6. 小–大写 toupper()
  7. write(fd)
  8. close();

server.c实现

#include "wrap.h"

#define SERV_PORT 9527

using namespace std;

int main()
{	
	int td1, td2, ret;
	ssize_t retR, retW;
	char buf[BUFSIZ], cilent_ip[1024];

	td1 = Socket(AF_INET, SOCK_STREAM, 0);

	struct sockaddr_in serv_addr;

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(SERV_PORT);
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	ret = Bind(td1, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

	ret = Listen(td1, 128);

	struct sockaddr_in cil_addr;
	socklen_t cil_addr_len;

	//cil_addr.sin_family = AF_INET;
	//cil_addr.sin_port = htons(SERV_PORT);
	//cil_addr.sin_addr.s_addr = 11111111111111111111111111111111111
	cil_addr_len = sizeof(cil_addr);

	td2 = Accept(td1, (struct sockaddr *)&cil_addr, &cil_addr_len);
	
	cout<<"客户端端口号:"<<ntohs(cil_addr.sin_port)<<endl;
	//cout<<"客户端网络号:"<<inet_ntop(cil_addr.sin_addr.s_addr)<<endl;
	cout<<"客户端网络号:"<<inet_ntop(AF_INET, &cil_addr.sin_addr.s_addr, cilent_ip, sizeof(cilent_ip))<<endl;

	while(1)
	{
		retR = read(td2, buf, sizeof(buf));
		if(retR == -1)
		{
			cout<<"read error"<<endl;
			exit(1);
		}

		retW = write(STDOUT_FILENO, buf, retR);
		if(retW == -1)
		{
			cout<<"write error"<<endl;
			exit(1);
		}

		for(int i = 0; i < retR; i++)
		{
			buf[i] = toupper(buf[i]);
		}

		retW = write(td2, buf, retR);
		if(retW == -1)
		{
			cout<<"write error"<<endl;
			exit(1);
		}
	}

	close(td1);

	close(td2);

	return 0;
}

client.c实现

#include <iostream>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <warp.h>

#define SERV_PORT 9527
using namespace std;

int main()
{
	char buf[BUFSIZ];

	int fd = Socket(AF_INET, SOCK_STREAM, 0);
	
	struct sockaddr_in serv_addr;
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(SERV_PORT);
	inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr.s_addr);
	//serv_addr.sin_addr.s_addr = ;

	int ret = Connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

	while(1)
	{
		write(fd, "hello\n", 5);
		ret = read(fd, buf, sizeof(buf));
		write(STDOUT_FILENO, buf, ret);
		sleep(1);
	}

	close(fd);

	return 0;
}

warp.h(改写accept、bind、connect等函数,使得在写server代码时不用检查函数调用是否出错)

#ifndef _WRAP_H
#define _WRAP_H

#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <ctype.h>
#include <arpa/inet.h>

void perr_exit(const char *s);
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
int Bind(int fd, const struct sockaddr *sa, socklen_t salen);
int Connect(int fd, const struct sockaddr *sa, socklen_t salen);
int Listen(int fd, int backlog);
int Socket(int family, int type, int protocol);

#endif

warp.c(warp.h中定义的函数实现)

#include "wrap.h"
#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>

using namespace std;

void perr_exit(const char *s)
{
	perror(s);
	exit(-1);
}

int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
{
	int n;

again:
	if ((n = accept(fd, sa, salenptr)) < 0) {
		if ((errno == ECONNABORTED) || (errno == EINTR))
			goto again;
		else
			perr_exit("accept error");
	}
	return n;
}

int Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{
	int n;

	if ((n = bind(fd, sa, salen)) < 0)
		perr_exit("bind error");

	return n;
}

int Connect(int fd, const struct sockaddr *sa, socklen_t salen)
{
	int n;

	if ((n = connect(fd, sa, salen)) < 0)
		perr_exit("connect error");

	return n;
}

int Listen(int fd, int backlog)
{
	int n;

	if ((n = listen(fd, backlog)) < 0)
		perr_exit("listen error");

	return n;
}

int Socket(int family, int type, int protocol)
{
	int n;

	if ((n = socket(family, type, protocol)) < 0)
		perr_exit("socket error");

	return n;
}

参考资料: https://www.bilibili.com/video/BV1iJ411S7UA?p=154&spm_id_from=pageDriver

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值