TCP通信流程分析
client:
- socket() 创建socket
- connect(); 与服务器建立连接
- write() 写数据到 socket
- read() 读转换后的数据。
- 显示读取结果
- close()
server:
- socket() 创建socket
- bind() 绑定服务器地址结构
- listen() 设置监听上限
- accept() 阻塞监听客户端连接
- read(fd) 读socket获取客户端数据
- 小–大写 toupper()
- write(fd)
- 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