注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

从C开始

 
 
 

日志

 
 

Socket编程  

2010-11-20 00:31:14|  分类: MFC |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

注意:

要用到socket函数,首先要包含头文件 Winsock2.h

其次是project –>Setting -> Link 库文件最后加入ws2_32.lib

或者调用 #pragma comment(lib, "ws2_32.lib")

 

基于TCP(面向连接)socket编程

服务器端程序:

1、创建套接字(socket)。

2、将套接字绑定到一个本地地址和端口上(bind)。

3、将套接字设为监听模式,准备接收客户请求(listen)。

4、等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。

5、用返回的套接字和客户端进行通信(send/recv)。

6、返回,等待另一客户请求。

7、关闭套接字。

 

客户端程序:

1、创建套接字(socket)。

2、向服务器发出连接请求(connect)。

3、和服务器端进行通信(send/recv)。

4、关闭套接字。

 

 

基于UDP(面向无连接)socket编程

服务器端(接收端)程序:

1、创建套接字(socket)。

2、将套接字绑定到一个本地地址和端口上(bind)。

3、等待接收数据(recvfrom)。

4、关闭套接字。

 

客户端(发送端)程序:

1、创建套接字(socket)。

2、向服务器发送数据(sendto)。

3、关闭套接字。

 

 

具体实现

WSAStartup函数

在利用套接字编程时,第一步需要加载套接字库,这通过WSAStartup函数来实现。该函数有两个功能,一是加载套接字库,二是进行套接字库的版本协商,也就是确定将要使用socket版本。

 

int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData );

 

wVersionRequested参数用来指定准备加载的Winsock库的版本。高字节指定所需要的Winsock库的副版本,而低字节则是主版本。

lpWSAData参数是一个返回值,指向WSADATA结构的指针,WSAStartup函数用其加载的库版本有关的信息填充这个结构。

注意:对于每一个WSAStartup函数的成功调用,在最后都对应一个WSACleanUp调用,以便释放为该应用程序分配的资源,终止Winsock动态库的使用。

 

 

socket函数

在加载了套接字库之后,就可以创建套接字了。

 

SOCKET socket( int af, int type, int protocol );

 

af参数指定地址族,对于TCP/IP协议的套接字,它只能是AF_INET(也可以写成PF_INET);

type参数指定socket类型,对于1.1版本的socket,它只支持两种类型的套接字,SOCK_STREAM指定产生流式套接字(TCP连接时使用);SOCK_DGRAM产生数据报套接字(UDP中使用);

protocol 参数是与特定的地址家族相关的协议,如果指定为0,那么系统就会根据地址格式和套接字类型自动选择一个合适的协议。

 

 

bind函数

在创建了套接字后,应该将该套接字绑定到本地的某个地址和端口上。

 

int bind( SOCKET s, const struct sockaddr FAR *name, int namelen );

 

s 指定要绑定的套接字;

name 是一个指向sockaddr 结构的指针,用来指定该套接字的本地地址信息。由于该地址结构是为所有的地址家族准备的,所以这个结构通常会随所使用的网络协议的不同而不同,所以要用第三个参数namelen 来指定该结构的长度。

在基于TCP/IPsocket编程过程中,可以用sockaddr_in 结构替换sockaddr 结构,以方便我们填写地址信息。

 

struct sockaddr_in{

 short sin_family;    //对于IP地址,一直是AF_INET

 unsigned short sin_port;  //指定将要分配给套接字的端口

 struct IN_ADDR sin_addr; //套接字的主机ip地址

 char sin_zero[8]; //填充数,使得sockaddr_insockaddr结构长度一样

};

 

sin_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地址转换为u_long类型,并将结果赋给成员S_addr

 

注意:为了简化程序的编写,sin_addr参数可以写成 xxsocketDDR_IN.sin_addr.S_un.S_addr = htonl(INADDR_ANY)他允许一个独立应用接受发自多个接口的回应。例如一台电脑上有两块网卡,有两个IP地址时,就不需要指定专门的IP地址了。

 

 

inet_addr inet_ntoa函数

要想让套接字使用多个IP中的一个地址,就必须指定实际地址。这时我们可以调用inet_addr函数来实现

 

unsigned long inet_addr( const char   FAR *cp  );

 

该函数需要一个字符串作为其参数,该字符串指定了以点分十进制格式表示IP地址(如192.168.0.1)。而且该函数会返回一个适合分配给in_addr结构中的S_addr成员的u_long类型。

 

Inet_ntoa函数会完成相反的转换,它接受一个in_addr结构体类型的参数,并返回一个以点分十进制格式表示的IP地址字符串。

char FAR * inet_ntoa(struct   in_addr in  );

 

 

listen函数

listen函数的作用是将一个指定的套接字设置为监听状态。

 

int listen( SOCKET s,  int backlog  );

 

backlog参数设置等待连接队列的最大长度,而不是在一个端口上同时可以进行连接的数目。例如,如果将backlog设置为2,那么当有3个请求同时到来时,前2个连接请求就会被放到等待请求队列中,然后由应用程序依次为这些请求服务,而第3个连接请求就被拒绝了。如果设置为SOMAXCONN,那么下层的服务提供者将负责为这个套接字设置最大的合理值。

 

 

accept函数

accept函数接受客户端发送的连接请求。

 

SOCKET accept(

  SOCKET s,

  struct sockaddr FAR *addr,

  int FAR *addrlen

);

 

s参数是我们已经设置监听的套接字

addr 参数是一个指向sockaddr 结构的指针,用来接收连接实体的地址,也就是当客户端向服务器发起连接,服务器接受这个连接时,保存发起连接的这个客户端的IP地址信息和端口信息。

addrlen 参数返回包含地址信息的长度。

 

 

send函数

send函数通过一个已建立连接的套接字发送数据。

 

int send(

  SOCKET s,             

  const char FAR *buf

  int len,              

  int flags             

);

 

s 是一个已经建立了连接的套接字

buf 指向一个缓冲区,包含将要发送的数据

len 是缓冲区的长度

flags 的值将影响函数的行为,一般将其设为0

 

 

recv函数

recv函数从一个已连接的套接字中接收数据

 

int recv(

  SOCKET s,      

  char FAR *buf

  int len,       

  int flags      

);

 

 

connect函数

connect函数将与一个特定的套接字建立连接。

 

int connect(

  SOCKET s,                         

  const struct sockaddr FAR *name

  int namelen                       

);

 

name 参数用来设定服务器端的地址信息。

namelen指定服务器端地址的长度

 

 

recvfrom函数

recvfrom函数将接收一个数据报信息并保存源地址。

 

int recvfrom(

  SOCKET s,                  

  char FAR* buf,             

  int len,                   

  int flags,                 

  struct sockaddr FAR *from

  int FAR *fromlen           

);

 

 

sendto函数

sendto函数将向一个特定的目的方发送数据

 

int sendto(

  SOCKET s,                       

  const char FAR *buf,           

  int len,                         

  int flags,                      

  const struct sockaddr FAR *to

  int tolen                       

);

 

 

htonshtonl函数

Windows Sockethtons函数将把一个u_short类型的值从主机字节顺序转换为TCP/IP网络字节顺序。

u_short htons( u_short hostshort );

 

htonl函数是把一个u_long类型的值从主机字节顺序转换为TCP/IP网络字节顺序。

u_long htonl( u_long hostlong );

 

 

  评论这张
 
阅读(228)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018