TCP与UDP的接口基本一样,多添加了3个接口。
1. listen
int listen (int __fd, int __n);
On success, zero is returned.
On error, -1 is returned, and errno is set to indicate the error.
监听_fd对应的端口号,相当于站在外面的接客员,一旦有cilent需要建立通信的请求,就会通知里面的招待员。
2. accpept
int accept (int __fd, __SOCKADDR_ARG __addr,
socklen_t *__restrict __addr_len);
On success, these system calls return a file de‐scriptor
for the accepted socket (a nonnegative integer).
On error, -1 is returned, errno is set to indicate the error,
and addrlen is left unchanged.
相当于接待员,将顾客从门外引入屋内,并分配一个小间fd(文件描述符),
用于与cilent后续进行交流,输入和输出,与文本无异,都是写入用户缓冲区,
有OS决定是写入硬盘,还是写入网络。
3. connect
int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);
If the connection or binding succeeds, zero is returned.
On error, -1 is returned, and errno is set to indicate the error.
addr就是struct sockaddr_in 输入型函数,保存了需要访问客户端的ip,端口。使用connect将cilent的套接字(也可以直接write和read)发送请求建立通信给server。
完整代码
makefile
all:server.out cilent.out
server.out:server.cpp
g++ -o server.out server.cpp
cilent.out:cilent.cpp
g++ -o cilent.out cilent.cpp
.PHONY:clean
clean:
rm -rf *.out
server.cpp
#include<iostream>
#include<memory>
#include"server.h"
using namespace std;
void manual()
{
printf("use manual: \n filename: port: \n");
}
int main(int argc,const char* argv[])
{
if(argc!=2)
{
manual();
exit(2);
}
string port=argv[1];
unique_ptr<server> myserver(new server(stoi(port)));
myserver->Init();
myserver->start();
return 0;
}
server.h
#include <iostream>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#include <arpa/inet.h>
#include <error.h>
#include <unistd.h>
using namespace std;
#define DeafultIp "0.0.0.0"
class server
{
int16_t port;
string ip;
int sockfd;
public:
server(int16_t _port, string _ip = DeafultIp) : port(_port), ip(_ip) {}
~server() {}
void Init()
{
sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in servermessage;
servermessage.sin_family = AF_INET;
servermessage.sin_port = htons(port);
servermessage.sin_addr.s_addr = htonl(INADDR_ANY);
socklen_t len = sizeof(servermessage);
if (bind(sockfd, (struct sockaddr *)&servermessage, len) == -1) // 0成功
{
cout << "error: " << strerror(errno) << endl;
exit(2);
}
if (listen(sockfd, 0) == -1) // 监听端口
{
cout << "error: " << strerror(errno) << endl;
exit(2);
}
}
void start()
{
struct sockaddr_in cilentmess;
socklen_t len = sizeof(cilentmess);
int acceptsock = accept(sockfd, (struct sockaddr *)&cilentmess, &len);
if (acceptsock == -1) // 0成功
{
cout << "error: " << strerror(errno) << endl;
exit(2);
}
int16_t port=ntohs(cilentmess.sin_port);
string ip=inet_ntoa(cilentmess.sin_addr);
char buffer[1024];
while (1)
{
int ret = read(acceptsock, buffer, sizeof(buffer));
if (ret > 0)
{
buffer[ret] = 0;
cout<<"ip: "<<ip<<" port: "<<port<<" : "<<buffer<<endl;
}
}
}
};
cilent.cpp
#include<iostream>
#include<memory>
#include"cilent.h"
using namespace std;
void manual()
{
printf("use manual: \n filename: ip: port: \n");
}
int main(int argc,const char* argv[])
{
if(argc!=3)
{
manual();
exit(2);
}
string port=argv[2];
string ip=argv[1];
unique_ptr<cilent> mycilent(new cilent(stoi(port),ip));
mycilent->Init();
mycilent->start();
return 0;
}
cilent.h
#include <iostream>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#include <arpa/inet.h>
#include <error.h>
#include <unistd.h>
using namespace std;
class cilent
{
int16_t port;
string ip;
int sockfd;
public:
cilent(int16_t _port, string _ip) : port(_port), ip(_ip) {}
~cilent() {}
void Init()
{
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
cout << "error: " << strerror(errno) << endl;
exit(2);
}
struct sockaddr_in servermess;
servermess.sin_family = AF_INET;
servermess.sin_port = htons(port);
servermess.sin_addr.s_addr = inet_addr(ip.c_str());
socklen_t len = sizeof(servermess);
if (connect(sockfd,(struct sockaddr*)& servermess,len)!=0)
{
cout<<"error: "<<strerror(errno)<<endl;
exit(2);
}
}
void start()
{
char buffer[1024];
while (1)
{
cout << "Please Enter: ";
if (fgets(buffer, sizeof(buffer), stdin))
{
string send_=buffer;
send_[send_.size()-1]=0;
write(sockfd,send_.c_str(),send_.size());
}
}
}
};