网络通信——TCP/UDP编程
网络通信
网络通信概述
IP和端口
数据传输三要素:源、目的、长度(网络传输中使用“IP和端口”表示源或目的)
网络传输两个对象(server、client)
两种传输方式:TCP/UDP
TCP和UDP原理上的区别
TCP/UDP网络通信交互图(1为tcp,2为udp)
网络编程主要函数
socket函数
intsocket(intdomain,inttype,intprotocol);
bind函数
intbind(intsockfd,conststructsockaddr*addr,socklen_taddrlen);
listen函数
intlisten(intsockfd,intbacklog);
accept函数
intaccept(intsockfd,structsockaddr*addr,socklen_t*addrlen);
connect函数
intconnect(intsockfd,conststructsockaddr*addr,socklen_taddrlen);
send函数
ssize_tsend(intsockfd,constvoid*buf,size_tlen,intflags);
recv函数
ssize_trecv(intsockfd,void*buf,size_tlen,intflags);
recvfrom函数
ssize_trecvfrom(intsockfd,void*buf,size_tlen,intflags,structsockaddr*src_addr,socklen_t*addrlen);
sendto函数
ssize_tsendto(intsockfd,constvoid*buf,size_tlen,intflags,conststructsockaddr*dest_addr,socklen_taddrlen);
server
#include/*SeeNOTES*/#include//网络编程所需文件#include#include#include#include#include#include#include/*socket*bind*listen*accept*send/recv*/#defineSERVER_PORT8888//服务器端口号#defineBACKLOG10//listen函数中最大同时监听连接数intmain(intargc,char**argv){intiSocketServer;intiSocketClient;structsockaddr_intSocketServerAddr;//服务器地址结构体structsockaddr_intSocketClientAddr;//客户端地址结构体intiRet;intiAddrLen;intiRecvLen;unsignedcharucRecvBuf[1000];intiClientNum=-1;signal(SIGCHLD,SIG_IGN);//忽略子进程退出信号,避免僵尸进程//1.创建套接字远程通信,TCP协议,0默认//执行成功返回文件描述符,失败返回-1iSocketServer=socket(AF_INET,SOCK_STREAM,0);if(-1==iSocketServer){printf("socketerror!\n");return-1;}tSocketServerAddr.sin_family=AF_INET;//网络通信//htons:主机字节序转网络字节序tSocketServerAddr.sin_port=htons(SERVER_PORT);/*hosttonet,short*/tSocketServerAddr.sin_addr.s_addr=INADDR_ANY;//表示可以和任何主机通信memset(tSocketServerAddr.sin_zero,0,8);//填充0//2.绑定本地地址和端口iRet=bind(iSocketServer,(conststructsockaddr*)&tSocketServerAddr,sizeof(structsockaddr));if(-1==iRet){printf("binderror!\n");return-1;}//3.监听10个连接iRet=listen(iSocketServer,BACKLOG);if(-1==iRet){printf("listenerror!\n");return-1;}while(1){iAddrLen=sizeof(structsockaddr);/*调用accept函数来等待客户端来连接,客户连接成功返回一个值,连接失败返回-1;*/iSocketClient=accept(iSocketServer,(structsockaddr*)&tSocketClientAddr,&iAddrLen);if(-1!=iSocketClient){iClientNum++;/*支持多个客户端连接,每有一个就调用fork,并创建一个子进程*///inet_ntoa:将网络字节序IP地址转换为点分十进制IP地址printf("Getconnectfromclient%d:%s\n",iClientNum,inet_ntoa(tSocketClientAddr.sin_addr));if(!fork)/*执行到fork后马上复制一个代码完全一样的子进程*/{/*父进程走fork=0;子进程走fork!=0;*///fork函数:创建一个子进程,父进程返回子进程ID,子进程返回0子进程的PID=父进程PID+1/*子进程的源码*/while(1){/*接受客户端发来的数据并显示出来*/iRecvLen=recv(iSocketClient,ucRecvBuf,999,0);if(iRecvLen
client
#include/*SeeNOTES*/#include#include#include#include#include#include#include/*socket*connect*send/recv*/#defineSERVER_PORT8888intmain(intargc,char**argv){intiSocketClient;structsockaddr_intSocketServerAddr;intiRet;unsignedcharucSendBuf[1000];intiSendLen;if(argc!=2){printf("Usage:\n");printf("%s\n",argv[0]);return-1;}//1.创建套接字iSocketClient=socket(AF_INET,SOCK_STREAM,0);//远程通信,TCP协议,0默认tSocketServerAddr.sin_family=AF_INET;tSocketServerAddr.sin_port=htons(SERVER_PORT);/*hosttonet,short*///tSocketServerAddr.sin_addr.s_addr=INADDR_ANY;if(0==inet_aton(argv[1],&tSocketServerAddr.sin_addr)){printf("invalidserver_ip\n");return-1;}memset(tSocketServerAddr.sin_zero,0,8);//2.发送连接请求连接服务器iRet=connect(iSocketClient,(conststructsockaddr*)&tSocketServerAddr,sizeof(structsockaddr));if(-1==iRet){printf("connecterror!\n");return-1;}while(1){if(fgets(ucSendBuf,999,stdin)){//3.发送数据iSendLen=send(iSocketClient,ucSendBuf,strlen(ucSendBuf),0);if(iSendLen
执行过程:在linux下先编译两个程序,然后执行server再打开新终端执行client,执行需要输入ip地址,此时在客户端发送字符串,服务器端可以接收到字符串
UDP编程
server
#include/*SeeNOTES*/#include#include#include#include#include#include#include#include/*socket*bind*sendto/recvfrom*/#defineSERVER_PORT8888intmain(intargc,char**argv){intiSocketServer;intiSocketClient;structsockaddr_intSocketServerAddr;structsockaddr_intSocketClientAddr;intiRet;intiAddrLen;intiRecvLen;unsignedcharucRecvBuf[1000];intiClientNum=-1;//1.创建socket套接字iSocketServer=socket(AF_INET,SOCK_DGRAM,0);if(-1==iSocketServer){printf("socketerror!\n");return-1;}tSocketServerAddr.sin_family=AF_INET;tSocketServerAddr.sin_port=htons(SERVER_PORT);/*hosttonet,short*/tSocketServerAddr.sin_addr.s_addr=INADDR_ANY;memset(tSocketServerAddr.sin_zero,0,8);//2.绑定本地ip地址和端口号iRet=bind(iSocketServer,(conststructsockaddr*)&tSocketServerAddr,sizeof(structsockaddr));if(-1==iRet){printf("binderror!\n");return-1;}while(1){iAddrLen=sizeof(structsockaddr);//3.接收数据recvfrom常用于无连接的udp通信iRecvLen=recvfrom(iSocketServer,ucRecvBuf,999,0,(structsockaddr*)&tSocketClientAddr,&iAddrLen);if(iRecvLen>0){ucRecvBuf[iRecvLen]='\0';printf("GetMsgFrom%s:%s\n",inet_ntoa(tSocketClientAddr.sin_addr),ucRecvBuf);}}//4.关闭socket套接字close(iSocketServer);return0;}
client
#include/*SeeNOTES*/#include#include#include#include#include#include#include/*socket*connect*send/recv*/#defineSERVER_PORT8888intmain(intargc,char**argv){intiSocketClient;structsockaddr_intSocketServerAddr;intiRet;unsignedcharucSendBuf[1000];intiSendLen;if(argc!=2){printf("Usage:\n");printf("%s\n",argv[0]);return-1;}//1.创建socket套接字iSocketClient=socket(AF_INET,SOCK_DGRAM,0);tSocketServerAddr.sin_family=AF_INET;tSocketServerAddr.sin_port=htons(SERVER_PORT);/*hosttonet,short*///tSocketServerAddr.sin_addr.s_addr=INADDR_ANY;if(0==inet_aton(argv[1],&tSocketServerAddr.sin_addr)){printf("invalidserver_ip\n");return-1;}memset(tSocketServerAddr.sin_zero,0,8);//2.连接服务器iRet=connect(iSocketClient,(conststructsockaddr*)&tSocketServerAddr,sizeof(structsockaddr));if(-1==iRet){printf("connecterror!\n");return-1;}while(1){if(fgets(ucSendBuf,999,stdin)){//3.发送数据iSendLen=send(iSocketClient,ucSendBuf,strlen(ucSendBuf),0);if(iSendLen
总结:TCP和UPD编程的区别
TCP
UDP
client
socket->connect->send/recv
socket->connect->send/recv(可以直接使用sendto,去掉connect)
server
socket->bind->listen->accept->send/recv
socket->bind->sendto/recvfrom