`
xitonga
  • 浏览: 583829 次
文章分类
社区版块
存档分类
最新评论

网络编程(套接字)

 
阅读更多
网络编程
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>
#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();
}
要加入ws2_32.lib库文件


6.2基于UDP的网络应用程序的编写

后面会有一个多线程聊天程序的编写

详见http://blog.csdn.net/walkerkalr/article/details/19510909




==参考VC++深入详解

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics