【Socket编程】Windows平台实现简单的UDP回声客户端和服务器端
UDP特点:无连接,不提供可靠传输服务,不提供流量控制,不提供拥塞控制
但是UDP相对TCP也有着自己独特的优势
- 无需为连接建立和连接拆除消耗额外的开销
- 无需为流量控制,拥塞控制消耗额外的开销
UDP和TCP在套接字数量上面的区别:
在TCP中,套接字之间是一对一的关系,若向十个客户端提供服务,就要创建10个套接字,而在UDP中,无论是客户端还是服务器端都是主要提供一个套接字。
UDP套接字不会维护连接状态,所以每次发送数据包都需要添加目标主机和端口
conneted UDP 套接字与 unconented UDP 套接字
未连接套接字就是每次都变更地址
已连接套接字就是向目标主机注册地址,多次发送数据包地址不变
UDP程序最核心的两个函数
#include
int sendto(SOCKET s,const char* buf,int len,int flags,const struct sockaddr* to,int tolen);
#include
int recvfrom(SOCKET s,const char* buf,int len,int flags,const struct sockaddr* from,int fromlen);
基于windows的回声服务器端和苦户端
/*client.c*/
#include
#include
#include
#include
#define BUF_SIZE 30
void ErrorHanding(char *message);
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET sock;
char message[BUF_SIZE];
int strLen;
SOCKADDR_IN servAdr;
if(argc!=3){
printf("Usage:%s \n",argv[0]);
exit(1);
}
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
ErrorHanding("WSAStartup() error!");
sock = socket(PF_INET,SOCK_DGRAM,0);
if(sock==INVALID_SOCKET)
ErrorHanding("scoket() error!");
memset(&servAdr,0,sizeof(servAdr));
servAdr.sin_family=AF_INET;
servAdr.sin_addr.s_addr=inet_addr(argv[1]);
servAdr.sin_port=htons(atoi(argv[2]));
connect(sock,(SOCKADDR*)&servAdr,sizeof(servAdr));
while(1){
fputs("Insert message(q to quit):",stdout);
fgets(message,sizeof(message),stdin);
if(!strcmp(message,"q\n")||!strcmp(message,"Q\n"))
break;
send(sock,message,strlen(message),0);
strLen=recv(sock,message,sizeof(message)-1,0);
message[strLen]=0;
printf("message from sever:%s",message);
}
closesocket(sock);
WSACleanup();
return 0;
}
void ErrorHanding(char* message){
fputs(message,stderr);
fputs("\n",stderr);
exit(1);
}
/*server.c*/
#include
#include
#include
#include
#define BUF_SIZE 30
void ErrorHanding(char *message);
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET servSock;
char message[BUF_SIZE];
int strLen;
int clntAdeSz;
SOCKADDR_IN servAdr,clntAdr;
if(argc!=2){
printf("Usage:%s \n",argv[0]);
exit(1);
}
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
ErrorHanding("WSAStartup() Error!");
servSock = socket(PF_INET,SOCK_DGRAM,0);
if(servSock == INVALID_SOCKET)
ErrorHanding("UDP CREATE SOCKET ERROR!");
memset(&servAdr,0,sizeof(servAdr));
servAdr.sin_family=AF_INET;
servAdr.sin_addr.s_addr=htonl(INADDR_ANY);
servAdr.sin_port=htons(atoi(argv[1]));
if(bind(servSock,(SOCKADDR*)&servAdr,sizeof(servAdr))==SOCKET_ERROR)
ErrorHanding("bind() Error!");
while(1){
clntAdeSz=sizeof(clntAdr);
strLen=recvfrom(servSock,message,BUF_SIZE,0,(SOCKADDR*)&clntAdr,&clntAdeSz);
sendto(servSock,message,strLen,0,(SOCKADDR*)&clntAdr,sizeof(clntAdr));
}
closesocket(servSock);
WSACleanup();
return 0;
}
void ErrorHanding(char* message){
fputs(message,stderr);
fputs("\n",stderr);
exit(1);
}