socket

socket

结构体

sockaddr

struct sockaddr{
    sa_family_t 		sin_family;
    char 				sa_data[14];
}

sockaddr_in 是为了保存ipv4地址信息的结构体

struct sockaddr_in{
    sa_family_t   	 	sin_family;				//地址族
    uint16_t  	   		sin_port;				//16位tcp/udp端口
    struct in_addr   	sin_addr;				//32位ip地址
    char				sin_zero[8];			//不适用
}
  • 使用时是在,bind,accept,connect中通过(SOCKADDR*)强制转换
struct in_addr{
    in_addr_t			s_addr;					//32位ipv4地址
}

数据类型 说明 头文件

uint16_t unsinged long(32-bit) sys/types.h

sa_family 地址族(adress family) sys/socket.h

socklen_len 长度 sys/socket.h

in_addr_t ip地址(uint32_t) netinet/in.t

in_port_t 端口地址(uint16_t) netinet/in.t

sin_family

  • AF_INET --------------------------------------IPV4使用的地址族
  • AF_INET6----------------------------------------IPV6使用的地址族
  • AF_LOCAL----------------------------------------本地通信中采用UNIX协议的地址族

sin_port

  • 保存16位端口号

sin_zero

  • 无特殊意义,只是为了让 sockaddr_in和sockaddr保持一致

字符序转换

主机字节序和网络字节序的转换

unsigned short htons(unsigned short);
unsigned short ntons(unsigned short);
unsigned long htonl(unsigned long);
unsigned long ntonl(unsigned long);
//理论上大端序不用更换成网络号
  • htons中的h表示主机(host)字序转换成网络字节序
  • ntons中的n表示网络(network)字节序转换成主字节序

字符串和整型的网络字节序的转换

#include<arpa/inet.h>
in_addr_t inet_addr(const char *string)
        //成功时返回32位整数型,失败时返回INADDR_NONE
#include<arpa/inet.h>
int inet_aton(const char* string,struct in_addr *addr)    //将改变的值存入addr中
    	//成功时返回1,失败是返回0

相反

#include<arpa/inet.h>
char * inet_nota(struct in_addr adr);
		//成功时返沪转换的字符串地址值,失败时返回-1

Windows服务端

区别于Liunx

  • 通过WSAStartup,WSACleanup函数初始化并清除套接字相关库
  • 把数据类型和变量名切换成Windows风格
  • 数据传输用recv,send函数,而不是read,write函数
  • 关闭套接字时用closesocket函数,而不是close函数
利用WSAStarup,WSACleanup函数初始化并清除套接字相关库
#include<winsock2.h>
WSADATA wasdata;
if(WSAStarup(MAKEWORD(2,2),&wsaData)!=0)
    ErrorHandling("WSAStarup() error!");
创建套接字
#include<winsock.h>
SOCKET socket(int af,int type,int protocol);							
	//成功时返回套接字句柄,失败时返回INVALID_SOCKET;

调用:

SOCKET hServSock = socket(PF_INET,SOCK_STREAM,0);
if(hServSock == INVALID_SOCKET)
    	ErrorHanding("socket() error!");
连接自身ip和端口号
#include<winsock.h>
int bind(SOCKET s,const struct sockaddr *name,int namelen);			  
	//成功返回0,失败返回SOCKET_ERROR

调用

SOCKADDR_IN servAdr;
memset(&servAdr,0,sizeof(servAdr));
servAdr.sin_family = AF_INET;
servAdr.sin_addr.s_addr = htonl(INADDR_ANY);					//区别于客户端的connect,这里的ip是直接自动获取的
servAdr.sin_port = htons(atoi(argv[1]));
if(bind(hServSock,(SOCKADDR*)&sercAdr,sizeof(servAdr))==SOCKET_ERROR)
    ErrorHandling("");
监听
#include<winsock.h>
int listen(SOCKET s,int backlog);
	//成功返回0,失败返回SOCKET_ERROR

调用

if(listen(hServSock,5)==SOCKET_ERROR)
    ErrorHandling("");
等待连接
#include<winsock.h>
int accept(SOCKET s,struct sockaddr * addr,int *addrlen);
	//成功返回套接字句柄,失败返回TNVALID_SOCKET

调用

SOCKADDR_IN clntAdr;
SOCKAT hClntSock;
int clntAdrsize;
clntAdrSize = sizeof(clntAdr);
hClntSock = accept(hServSock,(SOCKADDR*)&clntAdr, &clntAdrSize);	

Windows客户端

#include<winsock.h>
int connect(SOCKET s,const struct sockaddr* name,int namelen);
	//成功返回0,失败返回SOCKET_ERROR

调用

  • 除了函数名和ip获取方式,其余和服务端bind 一模一样
SOCKADDR_IN servAdr;
memset(&servAdr,0,sizeof(servAdr));
servAdr.sin_family = AF_INET;
servAdr.sin_addr.s_addr = inet_addr(argv[1]);				//区别于服务端的bind,这里的IP是输入的
servAdr.sin_port = htons(atoi(argv[2]));
if(connect(hServSock,(SOCKADDR*)&sercAdr,sizeof(servAdr))==SOCKET_ERROR)
    ErrorHandling("");
关闭套接字
#include<winsock.h>
int closesocket(SOCKET s);
	//成功时返回0,失败时返回SOCKET_ERROR
发送
#include<winsock2.h>
int send(SOCKET s,const char *buf,int len,int flags);
	//成功时返回传出字节数,失败时返回SOCKT_ERROR
接受
#include<winsock2.h>
int recv(SOCKET s,const char* buf,int len,int flags);
	//成功时返回收到的字节数(收到EFO时为0),失败时返回SOCKET_ERROR

UDP区别于TCP的地方
发送
#include<winsock2.h>
int sendto(int sock,void *buff,size_t nbytes,int flags,struct sockaddr *to,int tolen);
	//成功时返回传输的字节数,失败时返回SOCKET_ERROR
  • sock:用于传输数据的udp套接字文件描述符
  • buff:保存待传数据的缓冲地址值
  • nbytes:待传输的数据长度,以字节为单位
  • flags:可选项参数,若没有则传递0
  • to:存有目标地址信息的sockaddr结构体变量的地址值
  • addrlen:传递给参数to的地址值结构体变量长度
接受
#include<winsock2.h>
int sendto(int sock,void *buff,size_t nbytes,int flags,struct sockaddr *to,int tolen);
	//成功时返回收到的字节数,失败时返回SOCKET_ERROR
  • 基本同上

  • 如果一个udp套接字connect到了一个目标套接字,那么就不能再给其他套接字发送消息

Liunx服务端

创建套接字
#include<sys/socket.h>    
int socket(int domain,int type,int protocol);								
	//成功返回文件描述符,失败返回-1

连接自身ip和端口号
#include<sys/socket.h>    
int socket(int sockfd,struct sockaddr *myaddr,socklen_t addrlen);			 
	//成功返回0,失败返回-1

监听
#include<sys/socket.h>    
int listen(int sockfd,int backlog);
	//成功返回0,失败返回-1
等待连接
#include<sys/socket.h>    
int accept(int sockfd,struct sockaddr *addr,socklen_t addrlen);
	//成功返回文件描述符,失败返回-1

Liunx客户端

#include<sys/socket.h>    
int connect(int sockfd,struct sockaddr *serv_addr,socklen_t addrlen);
	//成功返回0,失败返回-1
文件读取
打开文件
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int open(const char* path,int flag);
	//成功时返回文件描述符,失败时返回-1
	//path:文件名的字符串地址
	//文件打开模式

打开模式

  • O_CREAT--------------------------------------------------------------------必要时创建文件
  • O_TRUNC--------------------------------------------------------------------删除全部现有数据
  • O_APPEND------------------------------------------------------------------维持现有数据,保存在后面
  • O_RDONLY------------------------------------------------------------------只读打开
  • W_WRONLY-----------------------------------------------------------------只写打开
  • O_RDWR----------------------------------------------------------------------读写打开

调用

#include<>
关闭文件
#include<unistd.h>
int close(int fd);
	//成功时返回0,失败时返回-1
  • fd,要关闭的文件或套接字的文件描述符
将数据写入文件
#include<unistd.h>
ssize_t write(int fd,const void * buf,size_t nbytes);
	//成功时返回要写入的字节数,失败时返回-1
  • fd: 显示数据传输对象的文件描述符
  • buf:保存要传输数据的缓冲地址值
  • nbytes:要传输数据的字节数
读取文件中的数据
#include<unistd.h>
ssize_t read(int fd,void * buf,size_t nbytes);
	//成功时返回收到的字节数(但遇到文件结尾则返回0),失败时返回-1
  • fd:显示数据接收对象的文件描述符
  • buf:要保存接收数据的缓冲地址值
  • nbytes:要接受数据的最大字节数
UDP区别于TCP的地方
发送
#include<sys/socket.h>
ssize_t sendto(int sock,void *buff,size_t nbytes,int flags,struct sockaddr *to,socklen_t addrlen);
	//成功时返回传输的字节数,失败时返回-1
  • sock:用于传输数据的udp套接字文件描述符
  • buff:保存待传数据的缓冲地址值
  • nbytes:待传输的数据长度,以字节为单位
  • flags:可选项参数,若没有则传递0
  • to:存有目标地址信息的sockaddr结构体变量的地址值
  • addrlen:传递给参数to的地址值结构体变量长度
接受
#include<sys/socket.h>
ssize_t sendto(int sock,void *buff,size_t nbytes,int flags,struct sockaddr *to,socklen_t addrlen);
	//成功时返回收到的字节数,失败时返回-1
  • 基本同上
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值