1.套接字的类型
1.1流式套接字SOCK_STREAM
提供面向连接、可靠的数据传输服务,数据无差错、无重复的发送,且按发送顺序接收。实际上它是基于TCP协议实现的。
1.2数据报套接字SOCK_DGRAM
提供无连接服务。数据包以独立包形式发送,不提供无措保证,数据可能丢失或重复,并且接收顺序混乱。数据报式套接字实际上是基于UDP协议实现的。
1.3原始套接字SOCK_RAW
2.基于TCP的socket编程
服务器器段流程:
1)创建套接字(socket)
2)将套接字绑定到本地地址和端口上(bind)
3)将套接字设为监听模式,准备接收客户请求(listen)
4)等待客户请求到来;当请求到来后,接收连接请求,返回一个新的对应于此次连接的套接字(accept)
5)用返回的套接字和客户端进行通信(send/recv)
6)返回,等待另一客户请求
7)关闭套接字
基于TCP的socket编程
1)创建套接字(socket)
2)向服务器发出连接请求(connect)
3)和服务器段进行通信(send/recv)
4)关闭套接字
在服务器端,当调用accept函数时,程序就会等待,等待客户端调用connect函数发出连接请求,然后服务器接收请求,于是双方就建立了连接。之后,服务器端和客户端就可以利用send和recv函数进行通信了。在客户端并不需要调用bind函数。因为服务器需要接收客户端的请求,所以必须告诉本地主机它打算在哪个IP地址和哪个端口上等待客户请求,因此必须调用bind函数来实现这一功能。而对客户端来说,当它发起连接请求,服务器端接收请求后,在服务器端就保存了该客户端的IP地址和端口信息。这样,对服务器端来说,一旦建立连接之后,实际上它保存了客户端的IP地址和端口的信息,因此就可以利用所返回的套接字调用send/recv函数与客户端进行通信。
3.基于UDP(面向无连接)的socket编程
接收端:
1)创建套接字socket
2)将套接字绑定到本地地址和端口上bind
3)等待接受数据recvfrom
4)关闭套接字
发送端:
1)创建套接字(socket)
2)向服务器发送数据sendto
3)关闭套接字
4.相关函数
int WSAStartup(//初始化Ws_2_32.dll的使用,加载套接字库
WORD wVersionRequested,
LPWSADATA lpWSAData
);
SOCKET socket (//创建套接字
int af,
int type,
int protocol );
int bind(//绑定本地的某个地址和端口,调用成功返回0,否则返回SOCKET_ERROR
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);
struct sockaddr {//sockaddr结构
u_short sa_family;
char sa_data[14];
};
struct sockaddr_in{//在TCP/IP中可以使用sockaddr_in代替sockaddr
short sin_family;
unsigned short sin_port;
IN_ADDR sin_addr;
char sin_zero[8];};
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;
};
unsigned long inet_addr (//将一个带点地址的字符串转换为IN_ADDR结构
const char *cp );
char FAR * inet_ntoa(//与上述函数功能相反,将IN_ADDR结构转化为字符串
struct in_addr in
);
int listen(//将指定套接字设置监听模式
SOCKET s,
int backlog
);
SOCKET accept(//接受客户端发送的连接请求
SOCKET s,
struct sockaddr FAR *addr,
int FAR *addrlen
);
int send(//发送数据
SOCKET s,
const char FAR *buf,
int len,
int flags
);
int recv(//接收数据
SOCKET s,
char FAR *buf,
int len,
int flags
);
int connect(//讲一个特定的套接字建立连接
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);
int recvfrom(//接受一个数据报信息并保存源地址
SOCKET s,
char FAR* buf,
int len,
int flags,
struct sockaddr FAR *from,
int FAR *fromlen
);
int sendto(//向一个特定的目的地发送数据
SOCKET s,
const char FAR *buf,
int len,
int flags,
const struct sockaddr FAR *to,
int tolen
);
u_short htons(//把一个u_short类型的值从主机字节顺序转换为TCP/IP网络字节顺序
u_short hostshort
);
u_long htonl(//把一个u_long类型的值从主机字节顺序转换为TCP/IP网络字节顺序
u_long hostlong
);
5.基于TCP的网络应用程序的编写
5.1服务器段程序
#include<Winsock2.h>
#include<stdio.h>
void main(){
//加载套接字库
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1,1);
err = WSAStartup(wVersionRequested, &wsaData);
if( err != 0){
return;
}
if(LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE(wsaData.wVersion) != 1){
WSACleanup();
return;
}
//创建用于监听的套接字
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);
//绑定套接字
bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
//将套接字设为监听模式,准备接收客户请求
listen(sockSrv,5);
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
while(1){
//等待客户请求到来
SOCKET sockConn = accept(sockSrv,(SOCKADDR*)&addrClient,&len);
char sendBuf[100];
sprintf(sendBuf,"Welcome %s to http://www.sunxin,org",
inet_ntoa(addrClient.sin_addr));
//发送数据
send(sockConn,sendBuf,strlen(sendBuf)+1,0);
char recvBuf[100];
//接收数据
recv(sockConn,recvBuf,100,0);
//打印接收的数据
printf("%s\n",recvBuf);
//关闭套接字
closesocket(sockConn);
}
}
5.2客户端程序
#include<Winsock2.h>要加入ws2_32.lib库文件
#include<stdio.h>
void main(){
//加载套接字库
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1,1);
err = WSAStartup(wVersionRequested, &wsaData);
if( err != 0){
return;
}
if(LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE(wsaData.wVersion) != 1){
WSACleanup();
return;
}
//创建套接字
SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr= inet_addr("127.0.0.1");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);
//向服务器发出连接请求
connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
//接收数据
char recvBuf[100];
recv(sockClient,recvBuf,100,0);
printf("%s\n",recvBuf);
//发送数据
send(sockClient,"This is lisi",strlen("this is lisi")+1,0);
closesocket(sockClient);
WSACleanup();
}
6.2基于UDP的网络应用程序的编写
后面会有一个多线程聊天程序的编写
详见http://blog.csdn.net/walkerkalr/article/details/19510909
==参考VC++深入详解