socket1.1网络编程

▲TCP与UDP
TCP模式:客户端先向服务端发起连接请求,服务端接受连接请求后才在客户端与服务端建立连接,优点是连接双方数据不易丢失。
UDP模式:通信双方不需要建立连接就可向对方发送或接收数据,优点是实时性较高,缺点是数据可能会丢失。

 

▲网络字节序
各种硬件对多字节数据的存储顺序不同,在起始地址处,有的机器先存入低位字节,而有的机器则先存入高位字节,如intel cpu将低位字节存入起始地址。在tcp/ip网络协议中使用的16位和32位整数采用高位先存的规则。
将使用本地字节序的数据转换成使用网络字节序的数据
u_long htonl(u_long)                  //32位整数
u_short htons(u_short)             //16位整数

 

▲IPV4地址转换
IPV4地址采用4字节表示地址,而人们通常使用点分十进制表示地址,如本机回路地址127.0.0.1
u_long inet_addr(char*)      //将点分十进制地址字符串转换为4字节表示的网络字节序地址
char* inet_ntoa(in_addr)     //将in_addr结构体中地址信息转换为点分十进制地址字符串

 

▲in_addr结构体
struct in_addr {
 union {
  struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
  struct { u_short s_w1,s_w2; } S_un_w;
  u_long S_addr;
 } S_un;
};
in_addr结构体用以表示ip地址信息,其内部是一个联合变量S_un。
in_addr addr;
addr.S_un.S_addr=inet_addr("127.0.0.1");   //指定ip信息为127.0.0.1
/
addr.S_un.S_addr=htonl(INADDR_ANY);    //指定ip信息为本机获得的任何ip地址

 

▲sockaddr与sockaddr_in结构体
struct sockaddr
{
  u_short sa_family;       //地址族,对于TCP/IP只能取AF_INET
  char sa_data[14];       //ip地址和端口信息
};


struct sockaddr_in
{
short sin_family;                //地址族,对于TCP/IP只能取AF_INET    
unsigned short sin_port;   //(网络字节序)端口号,1024以下端口由系统保留
struct in_addr sin_addr;   //ip地址结构体
char sin_zero[8];              //填充数据
};

sockaddr与sockaddr_in结构体都包含有建立网络连接所需的地址族、ip地址、端口号信息,然而sockaddr数据成员较笼统,因此多使用sockaddr_in结构体,在需要使用sockaddr数据处,可用sockaddr_in数据强制转换为sockaddr类型代替即可,sockaddr_in结构体会使用填充数据以使其位宽与sockaddr结构体位宽保持一致。

 

▲加载/卸载socket库
WSADATA wsadata;       //WSADATA结构体变量
WSAStartup(MAKEWORD(1.1),&wsadata);    //加载socket库
在MAKEWORD宏中指定要加载的socket库版本,wsadata返回的信息中包含实际加载的库版本和当前系统socket的最高版本。
WSACleanup();   /不再使用socket库时应卸载socket库,释放资源

 

▲创建/关闭socket
SOCKET socket(int af,int type,int protocol)   //按指定的信息创建socket
af——地址族,对于TCP/IP协议只能去AF_INET
type——socket类型,SOCK_STREAM对应TCP,SOCK_DGRAM对应UDP
protocol——地址族相关协议,取0让系统自行处理
closesocket(...)       //关闭socket,释放资源

 

▲绑定IP地址与端口
bind(SOCKET s,const struct sockaddr FAR *name,int namelen) //将socket绑定到指定的ip地址与端口
s——未绑定的socket
name——sockaddr结构体指针,包含指定的地址族、ip地址和端口信息
namelen——sockaddr结构体大小

 

▲连接的监听,发起,接受
listen(SOCKET s,int backlog)    //将socket设置为监听模式
s——已绑定,未连接的socket
backlog——请求队列的长度,设为SOMAXCONN时,由系统设置合理值。超出队列长度的连接请求将被拒绝。
SOCKET accept(SOCKET s,struct sockaddr FAR *addr,int FAR *addrlen)  //接受连接请求
s——处于监听状态的socket
addr——sockaddr结构体指针,返回发起连接方的ip和端口信息
addrlen——sockaddr结构体长度,必须先赋初值
accept(...)会一直等待连接请求并暂停线程,接受连接后返回一个与对方连接的socket。
int connect(SOCKET s,const struct sockaddr FAR *name,int namelen)  //发起连接请求
s——未连接的socket
name——sockaddr结构体指针,指定向哪个ip与端口发起连接请求
namelen——sockaddr结构体大小
在发起连接请求时,线程会暂停,直到请求超时,或者对方接受连接,此时s成为连接状态的socket

 

▲发送/接收数据
TCP模式:
int send(SOCKET s,const char FAR *buf,int len,int flags)    //发送数据
s——已连接的socket
buf——待发送数据的地址
len——数据的大小
flags——发送方式,一般取0
send(...)返回发送的总字节数,可能比len指定的小。
int recv(SOCKET s,char FAR *buf,int len,int flags)   //接收数据
s——已连接的socket
buf——存放数据所用内存的地址
len——数据内存的大小
flags——接受方式,一般取0
recv(...)会一直等待数据接收并暂停线程,接收数据后返回接收数据的字节数。
///
UDP模式:
int sendto(SOCKET s,const char FAR *buf,int len,int flags,const struct sockaddr FAR *to,int tolen)   //发送数据
s——(可能处于连接态的)socket
buf——待发送数据的地址len——数据的大小
flags——发送方式,一般取0
to——sockaddr结构体指针,指定接收方ip地址与端口信息
tolen——sockaddr结构体大小
sendto(...)返回发送的总字节数,可能比len小。
int recvfrom(SOCKET s,char FAR* buf,int len,int flags,struct sockaddr FAR *from,int FAR *fromlen)   //接收数据
s——已绑定的socket
buf——存放数据所用内存的地址
len——数据内存的大小
flags——接收方式,一般取0
from——sockaddr结构体指针,存放发送方ip地址与端口信息
formlen——sockaddr结构体大小,必须赋初值
recvform(...)会一直等待数据接收并暂停线程,接收数据后返回接收数据的字节数。
-----------------------------------------------------------------------------------------------

▲基于TCP的服务器端程序(示例)

1.初始化

WSADATA wsadata;

WSAStartup(MAKEWORD(1,1),&wsadata);     //加载socket库

SOCKET sersocket=socket(AF_INET,SOCK_STREAM,0);   //创建socket

2.将socket绑定到一个ip地址和端口上

sockaddr_in addrin;

addrin.sin_family=AF_INET;

addrin.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");   //服务器ip地址

addrin.sin_port=htons(1025);     //端口

bind(sersocket,(sockaddr*)&addrin,sizeof(sockaddr));    //绑定

3.监听,等待并接受连接

listen(sersocket,1);       //监听模式

sockaddr_in conaddr;

int len=sizeof(conaddr);

SOCKET consocket=accept(sersocket,(sockaddr*)&conaddr,&len);  //等待并接受连接

4.与连接的客户端通信

char min[128]={0};

recv(consocket,min,128,0);   //接受数据

char mout[128]={...};

send(consocket,mout,strlen(mout),0);  //发送数据

5.释放资源

closesocket(sersocket);   //关闭socket

WSACleanup();      //卸载socket库

 

▲基于TCP的客户端程序(示例)

1.初始化

WSADATA wsadata;

WSAStartup(MAKEWORD(1,1),&wsadata);       //加载socket库

SOCKET clisocket=socket(AF_INET,SOCK_STREAM,0);   //创建socket

2.向服务器发送连接请求

sockaddr_in addrin;

addrin.sin_family=AF_INET;

addrin.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");   //服务器ip地址

addrin.sin_port=htons(1025);              //端口

connect(clisocket,(sockaddr*)&addrin,sizeof(sockaddr));   发起连接请求

3.与接受连接的服务器通信

char mout[128]={...};

char min[128]={0};

recv(clisocket,min,128,0);     //接收数据

send(clisocket,mout,strlen(mout)+1,0);   //发送数据

4.释放资源

closesocket(clisocket);    //关闭socket

WSACleanup();        //卸载socket库

 

▲基于UDP的服务器程序(示例)

1.初始化

WSADATA wsadata;

WSAStartup(MAKEWORD(1,1),&wsadata);     //加载socket库

SOCKET socketser=socket(AF_INET,SOCK_DGRAM,0);    //创建socket

2.将socket绑定到一个ip地址和端口上

sockaddr_in addrin,addrincon;

addrin.sin_family=AF_INET;

addrin.sin_port=htons(2012);     //端口

addrin.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");    //服务器ip地址

bind(socketser,(sockaddr *)&addrin,sizeof(sockaddr));    //绑定

3.等待数据或发送数据

int len=sizeof(sockaddr);

char din[128]={0};

recvfrom(socketser,din,128,0,(sockaddr *)&addrincon,&len);   //接收数据

char dout[128]={...};

sendto(socketser,dout,strlen(dout)+1,0,(sockaddr *)&addrincon,len);   //发送数据

4.释放资源

closesocket(socketser);    //关闭socket

WSACleanup();      //卸载socket库

 

▲基于UDP的客户端程序(示例)

1.初始化

WSADATA wsadata;

WSAStartup(MAKEWORD(1,1),&wsadata);     //加载socket库

SOCKET socketcon=socket(AF_INET,SOCK_DGRAM,0);    //创建socket

2.发送数据或等待数据

sockaddr_in addrin,addrincon;

addrin.sin_family=AF_INET;

addrin.sin_port=htons(2012);      //端口

addrin.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");    //服务器ip地址

char dout[128]={...};

sendto(socketcon,dout,strlen(dout)+1,0,(sockaddr *)&addrin,sizeof(sockaddr));   //发送数据

char din[128]={0};

recvfrom(socketcon,din,128,0,(sockaddr *)&addrincon,&len);    //接收数据

3.释放资源

closesocket(socketcon);    //关闭socket

WSACleanup();     //卸载socket库


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值