TCP/IP 地址家族统一的套接字地址结构定义如下:
struct sockaddr_in {
short sin_family; //指定地址家族,即地址格式
unsigned short sin_port; //端口号码
struct in_addr sin_addr; //IP地址
char sin_zero[8]; //需要指定为0
}
sin_family 指定使用该套接字地址的地址家族. 这里必须设置为 AF_INET,表示程序所使用的地址家族是 TCP/IP; sin_zero[8] 主要是为了与第一个版本的套接字地址结构大小相同而设置,实际使用时,将这 8 个字节设置为 0 即可. sin_addr 表示 32 为的 IP 地址结构 结构定义如下:
struct in_addr {
union {
struct {
u_char s_b1,
s_b2,
s_b3,
s_b4;
}
S_un_b; //用4个u_char字符描述IP地址
struct {
u_short s_w1,
s_w2;
}
S_un_w; //用2个u_short类型描述IP地址
u_long S_addr; //用1个u_long类型描述IP地址
}
S_un;#define s_addr S_un.S_addr
};
通常,使用一个 u_long 类型的字符进行描述 IP 地址即可.
sockaddr_in addr;
addr.sin_addr.S_un.S_addr = inet_addr("218.6.132.5");
Socket 套接字编程中,传输数据的排列顺序以网络字节顺序和主机字节顺序为主. 数据在主机存储时,是以主机字节顺序存储的. 数据要通过网络发送,需要转换为网络字节顺序.否则会造成损坏. 网络字节是将重要的字节优先存储,而主机字节顺序则相反. Winsock 中的网络字节和主机字节的转换函数 主机字节 -> 网络字节 u_short htons(u_short hostshort); //u_short 类型的 IP 地址 u_long htonl(u_long hostlong); //u_long unsigned long inet_addr(const char FAR* cp);// 字符串 IP 网络字节 -> 主机字节 u_long ntohl(u_long hostlong);//u_long u_short ntols(u_short hostshort);//u_short char FAR* inet_ntoa(struct in_addr in);// 字符串 IP 具体使用:
sockaddr_in addrTo;
addrTo.sin_family = AF_INET;
addrTo.sin_port = htons(8900);
addrTo.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
char address[] = inet_ntoa(addrTo.sin_addr.S_un.S_addr);
Socket 相关函数 1. 创建套接字 CSocket 类创建套接字是通过其构造函数创建的 CSocket :: CSocket(); 创建 CSocket 对象 CSocket sock; 或 CSocket *sock; sock = new CSocket; 2. 绑定地址信息 如果套接字对象是服务器套接字,那么该套接字应该调用该类的函数 Bind() 将套接字对象与服务器地址信息绑定在一起. BOOL Bind(const SOCKADDR* lpSockAddr,int nSockAddrLen); lpSockAddr 地址结构 nSockAddrLen 地址结构长度 地址绑定成功后,还要调用函数 Listen() 在指定端口监听客户端的连接请求. 函数 Listen() 的原型如下: BOOL Listen(int nConnectionBackLog = 5); nContectionBackLog 表示套接字监听客户请求的最大数目.有效范围 1~5. 具体调用
CSocket sock;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
addr.sin_addr.S_un.s_addr = inet_addr("127.0.0.1");
sock.Bind((SOCKADDR * ) addr, sizeof(addr)); //绑定套接字的地址结构
sock.Listen(5);
3. 连接服务器 客户端创建套接字成功后,调用函数 Connect() 向服务器发送连接请求. BOOL Connect(const SOCKADDR* lpSockAddr,int nSockAddrLen); lpSockAddr 连接的服务器地址结构 nSockAddrLen 服务器地址结构长度 具体调用:
CSocket sock;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
addr.sin_addr.S_un_S_addr = inet_addr("127.0.0.1");
sock.Connect((SOCKADDR * ) addr, sizeof(addr)); //连接服务器
4. 数据交换 通过 Send() 和 Receive() 进行数据交换 函数原型 virtual int Send(const void lpBuf,int nBuflen,int nFlags = 0); virtual int Receive(void* lpBuf,int nBuflen,int nFlags = 0); lpBuf: 数据缓冲区地址 nBuflen: 数据缓冲区的大小 nFlags : 数据发送或接收标志,一般情况都设置为 0 ...
char buff[] = 'a';
sock.Send( & buff, sizeof(buff), 0);
sock.Receive( & buff, sizeof(buff), 0);
5. 关闭套接字对象 服务端和客户端的通信完成后,调用函数 Close() 将套接字对象关闭 sock.Close(); 注意: CSocket 类的头文件 afxsock.h 使用时,必须引入此文件 服务器端代码:
// SocketSever.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"#include < winsock2.h > #include < windows.h > #pragma comment(lib, "WS2_32.lib") int main(int argc, char * argv[]) {
//1.用户初始化套接字库
WSADATA data; //定义WSADATA结构体对象
WORD w = MAKEWORD(2, 0); //定义版本号
char sztext[] = "欢迎你\r\n"; //定义并初始化发送到客户端的字符数组
: :WSAStartup(w, &data); //初始化套接字库
//2.创建套接字
SOCKET s,
s1; //定义连接套接字和数据收发套接字句柄
s = ::socket(AF_INET, SOCK_STREAM, 0); //创建TCP套接字
sockaddr_in addr,
addr2; //定义套接字地址结构
int n = sizeof(addr2); //获取套接字地址结构大小
addr.sin_family = AF_INET;
addr.sin_port = htons(75);
addr.sin_addr.S_un.S_addr = INADDR_ANY;
//3.绑定地址信息及启动监听
: :bind(s, (sockaddr * ) & addr, sizeof(addr)); //绑定套接字
: :listen(s, 5);
printf("服务器已经启动 \r\n");
//4.监听及接收请求
while (true) {
s1 = ::accept(s, (sockaddr * ) & addr2, &n); //接收连接请求
if (s1 != NULL) {
printf("%s 已经连接上\r\n", inet_ntoa(addr2.sin_addr));: :send(s1, sztext, sizeof(sztext), 0);
}
//5.关闭套接字对象
: :closesocket(s);: :closesocket(s1);
//6.释放套接字库
: :WSACleanup();
if (getchar()) {
return 0;
} else {: :Sleep(100);
}
}
}
客户端代码:
// SocketClient.cpp : Defines the entry point for the console application.
//
#include < stdio.h > #include < winsock2.h > #include < windows.h > #pragma comment(lib, "WS2_32.lib") int main(int argc, char * argv[]) {
//1.用户初始化套接字库
WSADATA data; //定义WSADATA结构体对象
WORD w = MAKEWORD(2, 0); //定义版本号
: :WSAStartup(w, &data); //初始化套接字库
//2.创建套接字
SOCKET s; //定义连接套接字
char sztext[10] = {
0
};
s = ::socket(AF_INET, SOCK_STREAM, 0); //创建TCP套接字
sockaddr_in addr; //定义套接字地址结构
addr.sin_family = AF_INET;
addr.sin_port = htons(75);
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
printf("客户端已经启动 \r\n");
//3.连接服务器
: :connect(s, (sockaddr * ) & addr, sizeof(addr));
//4.接收服务器消息
: :recv(s, sztext, sizeof(sztext), 0);
printf("%s \r\n", sztext);
//5.关闭套接字对象
: :closesocket(s);
//6.释放套接字库
: :WSACleanup();
if (getchar()) {
return 0;
} else {: :Sleep(100);
}
}
来源: http://lib.csdn.net/article/embeddeddevelopment/34568