目录
1.学习网络编程前的一些基础知识
2.UDP(user datagram protocol)协议的特点
3.使用有UPD编写套接字
4.使用TCP编写套接字
4.2.TCP客服端
4.3.TCP服务器端
4.4.单进程版本(没有人会使用)
4.5.多进程版本
4.6.多线程版本
5.把套接字封装
1.1.IP地址
1.2.端口号(port)
1.3.TCP/IP四层模型
1.4.网络字节序
有系统提供的接口
UDP协议是一个传输层协议
3.1.服务器端
3.1.1.创建套接字
int sock=socket(AF_INET,SOCK_DGRAM,0);//创建套接字if(sock<0){std::cerr<<"socket fail: "<
3.1.2.bind服务器
网络字节序就是大端字节序(低位放在高地址上),使用相同的字节序便于网络间通信;
服务器不用bind一个固定的IP的原因
struct sockaddr_in local;local.sin_family=AF_INET;local.sin_port=htons(port);//1.需要将人识别的点分十进制,字符串风格IP地址,转化为4字节整数IP.2.考虑大小端的问题//1.云服务器,不允许bind公网IP,另外,在一般编写也不会指明IP.2.一般主机有多个IP,如果只是bind一个IP,发给其他IP的数据就不会交给主机处理;//INADDR_ANY只要是发给这个主机的数据都会被处理local.sin_addr.s_addr=INADDR_ANY;if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)//bind主机{std::cerr << "bind error : " << errno << std::endl;return 2;}
3.1.3.传递接受数据
//业务逻辑char message[1024];bool quit=false;while(!quit){//保存发送端信息struct sockaddr_in peer; socklen_t len=sizeof(peer);//接受数据ssize_t s=recvfrom(sock,message,sizeof(message)-1,0,(struct sockaddr*)&peer,&len);if(s>0){message[s]=0;std::cout<<"client# "<
3.2.客户端
#include
#include
#include
#include
#include
#include
#include
#include//client serverIP serverPort
int main(int argc,char* argv[])
{if(argc!=3){std::cout<<"请按格式输入: client serverIP serverPort"<>message;sendto(sock,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));struct sockaddr_in tmp;socklen_t tlen=sizeof(tmp);char buffer[1024];ssize_t s=recvfrom(sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&tmp,&tlen);if(s>0){std::cout<<"server say#: "<
4.1.TCP的特点
TCP是一个传输层协议,和UDP的特点相反
先写的客户端,因为服务器端会写多个版本
#include
#include
#include
#include
#include
#include
#include
#include
#includevoid Usage()
{std::cout<<"usage:./client server_IP server_port"<
4.3.1.创建套接字和bind服务器
//建立套接字int listen_sock=socket(AF_INET,SOCK_STREAM,0);if(listen_sock<0){std::cerr<<"socket"<
4.3.2.listen设为聆听状态
//listen状态listen(listen_sock,5);
4.3.3.accept接受客户端的连接,并返回一个文件描述符
struct sockaddr_in tmp;
socklen_t tlen=sizeof(tmp);
//建立连接
int fd=accept(listen_sock,(struct sockaddr*)&tmp,&tlen);
int main()
{//...创建套接字、bind、listen都省略了,每次都一样冗余while(1){struct sockaddr_in tmp;socklen_t tlen=sizeof(tmp);//建立连接int fd=accept(listen_sock,(struct sockaddr*)&tmp,&tlen);if(fd<0){std::cerr<<"accept "<0){buffer[s]=0;std::cout<<"client to server:"<
4.5.1.父进程是一个循环,他要一直接收新的客服端不能等待子进程,解决方法
父进程等待子进程,子进程创建后再创建孙子进程执行后序代码,子进程秒退等待时间可以忽略不计;下面代码
pid_t pid = fork();if(pid<0){continue;}else if(pid==0){//子进程close(listen_sock);if(fork()>0)exit(0);//子进程创建就直接退出,创建的孙子进程执行后序代码,孙子进程变成孤儿进程被1号进程领养serviceIO(fd);close(fd);exit(0);}else{//父进程close(fd);//子进程的PCB以父进程的PCB做模板初始化,不是共享的//waitpid(&pid,NULL,0);//父进程等待子进程,子进程创建后再创建孙子进程执行后序代码,子进程秒退等待时间可以忽略不计}
2.signal(SIGCHLD,SIG_IGN);//忽略SIGCHLD信号,子进程将自动释放;
2.关闭不用的文件描述符,父进程关闭accept返回的文件描述符,子进程关闭socket返回的文件描述符
void serviceIO(const int& fd)
{//1.单进程version,做成一个函数while(1){char buffer[1024]={0};ssize_t s=read(fd,buffer,sizeof(buffer));if(s>0){buffer[s]=0;std::cout<<"client to server:"<
void serviceIO(const int& fd)
{//1.单进程versionwhile(1){char buffer[1024]={0};ssize_t s=read(fd,buffer,sizeof(buffer));if(s>0){buffer[s]=0;std::cout<<"client to server:"<
#pragma once
#include
#include
#include
#include
#include
#includenamespace ns_socket{class sock{public:static int Socket(){int sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){std::cerr<<"socket"<