二 socket
1.基于TCP(面向连接)的socket编程
服务器端程序:
1.创建套接字(socket).
2.将套接字绑定到一个本地地址和端口上(bind).
3.将套接字设为监听模式,准备接收客户请求(listen).
4.等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept).
5.用返回的套按字和客户端进行通信(send/recv).
6.返回,等待另一个客户请求.
7.关闭套按字.
客户端程序:
1.创建套接字(socket).
2.向服务器发出连接请求(connect).
3.和服务器端进行通信(send/recv).
4.关闭套接字.
2.基于UDP(面向无连接)的socket编程
服务器端:
1.创建套接字(socket).
2.将套接字绑定到一个本地地址和端口上(bind).
3.等待接收数据(recvfrom).
4.关闭套接字.
客户端:
1.创建套接字(socket).
2.向服务器发送数据(sendto).
3.关闭套接字.
3.项目实例
基于TCP(面向连接)的socket编程实例
1)相关函数
----------- 加载socket库 begin ---------------
WSAStartup---加载套接字库,套接字库的版本协商
MAKEWORD---通过同时指定值来创建一个WORD值
WSAData---用WSAStartup获取的版本信息填充在WSAData结构体中
LOBYTE---获取WORD低字节
HIBYTE---获取WORD高字节
WSACleanup---终止使用Winsock,释放资源
----------- 加载socket库 end ---------------
----------- 创建socket begin---------------
socket---创建一个套接字
----------- 创建socket end ---------------
----------- 绑定socket begin ---------------
bind---用一个套接字关联一个本地地址
sockaddr
sockaddr_in
in_addr
htonl---转换为一个u_long从主机字节序到TCP/IP网络字节序
htons---转换为一个u_short从主机字节序到TCP/IP网络字节序
----------- 绑定socket end ---------------
----------- socket监听 begin ---------------
listen---将套接字设定为监听模式,以监听连接请求
----------- socket监听 end ---------------
----------- 等待客户端连接请求 begin ---------------
accept---等待客户端连接请求
----------- 等待客户端连接请求 end ---------------
----------- 向客户端发送请求数据 begin ---------------
send---对连接的套接字发送请求的数据
inet_ntoa---接受in_addr类型参数,返回一个点分十进制格式的IP地址的字符串
----------- 向客户端发送请求数据 end ---------------
----------- 接收数据 begin ---------------
recv---从一个已连接的套接字或者一个绑定到未连接的套接字接收数据
----------- 接收数据 end ---------------
int WSAStartup( //The WSAStartup function initiates use of the Winsock DLL by a process.
WORD wVersionRequested,
LPWSADATA lpWSAData //[out] Pointer to the WSADATA structure that is to receive details of the Windows Sockets implementation.
);
wVersionRequested:指定要加载的Winsock库的版本.高位字节指定库的副版本,低位字节指定主版本.可用MAKEWORD(x,y)(其中,x是低位字节(主版本),y是高位字节(副版本)(笔者注:原讲义在此处是:x是高位字节, y是低位字节,笔者参考MSDN Library-Visual Studio 2008 SP1 后作了修改))方便地获得wVersionRequested的正确值.
lpWSAData:是指向WSADATA结构的指针,WSADATA接收Windows Sockets 实现的详细信息.(WSAStartup用其加载的库版本有关的信息填在这个结构中)
成功调用WSAStartup后,在最后都对应一个WSACleanUp调用,以释放为应用程序分配的资源.
int WSACleanup (void); //The WSACleanup function terminates use of the Winsock 2 DLL (Ws2_32.dll).
WORD MAKEWORD( //The MAKEWORD macro creates a WORD value by concatenating the specified values.
BYTE bLow, //Specifies the low-order byte of the new value.
BYTE bHigh //Specifies the high-order byte of the new value.
);
typedef struct WSAData { //The WSADATA structure contains information about the Windows Sockets implementation.
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR* lpVendorInfo;
} WSADATA, *LPWSADATA;
BYTE LOBYTE( //The LOBYTE macro retrieves the low-order byte from the specified value.
WORD wValue
);
BYTE HIBYTE( //The HIBYTE macro retrieves the high-order byte from the given 16-bit value.
WORD wValue
);
----------------------------------------------------
SOCKET socket( //This function creates a socket that is bound to a specific service provider.
int af, //[in] Address family specification.
int type, //[in] Type specification for the new socket. SOCK_STREAM | SOCK_DGRAM | SOCK_RAW
int protocol //[in] Protocol to be used with the socket that is specific to the indicated address family.
);
the following list shows the possible value of protocol type :
IPPROTO_IP
IPPROTO_IPV6
IPPROTO_TCP
IPPROTO_UDP
SOL_SOCKET
AF_INET //The AF_INET address family is the address family for IPv4.
--------------------------------------
int bind( //This function associates a local address with a socket.
SOCKET s,
const struct sockaddr FAR* name,
int namelen
);
struct sockaddr { //The sockaddr structure varies depending on the protocol selected.
//Except for the sin*_family parameter, sockaddr contents are expressed in network byte order.
u_short sa_family;
char sa_data[14];
};
sockaddr 结构体是为所有的地址家族准备的,通常会随所使用的网络协议不同而不同,会用其它相关结构体来替换sockaddr这个结构体.
sa_data是一块内存区,用来放置与协议相关的具体地址信息.对不同的协议家族,必须用来同的结构体来替换sockaddr.在TCP/IP协议家族中,可以用sockaddr_in来替换sockaddr.
struct sockaddr_in { //In the Internet address family, this structure is used by Windows Sockets to specify a local or remote endpoint
// address to which to connect a socket. This is the form of the sockaddr structure specific to the Internet
// address family and can be cast to sockaddr.
short sin_family; //Address family; must be AF_INET.
u_short sin_port; //Internet Protocol (IP) port.
struct in_addr sin_addr; //IP address in network byte order.
char sin_zero[8]; //Padding to make structure the same size as SOCKADDR.
};
sockaddr_in如果调用成功,则返回0,调用不成功,则返回SOCKET_ERROR,可用WSAGetLastError函数取得错误信息.
typedef struct in_addr { //The in_addr structure represents an IPv4 Internet address.
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; //An IPv4 address formatted as four u_chars.
struct { u_short s_w1,s_w2; } S_un_w; //An IPv4 address formatted as two u_shorts.
u_long S_addr; //An IPv4 address formatted as a u_long.
} S_un;
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;
将IP地址指定为INADDR_ANY,允许一个独立应用接受发自多个接口的回应.
u_long htonl( //The htonl function converts a u_long from host to TCP/IP network byte order (which is big endian).
__in u_long hostlong
);
u_short htons( //The htons function converts a u_short from host to TCP/IP network byte order (which is big-endian).
__in u_short hostshort
);
--------------------------
int listen( //This function places a socket at a state where it is listening for an incoming connection.
SOCKET s,
int backlog //等待连接的最大长度
);
--------------------------
SOCKET accept( //This function permits an incoming connection attempt on a socket.
SOCKET s,
struct sockaddr FAR* addr, //save IP address and port of clients
int FAR* addrlen
);
----------------------------
int send( //This function sends data on a connected socket.
SOCKET s,
const char FAR* buf,
int len,
int flags
);
char* FAR inet_ntoa( //The inet_ntoa function converts an (Ipv4) Internet network address
// into a string in Internet standard dotted-decimal format.
__in struct in_addr in
);
---------------------------------
int recv( //The recv function receives data from a connected socket or a bound connectionless socket.
__in SOCKET s,
__out char* buf,
__in int len,
__in int flags
);