背景原因及概念:
网络连接基本过程:就像文件句柄和窗口一样可以看成是一个流接口,只要配置好接口对象属性,连通操作流程或网络,直接向这个接口发送和读取字节流就可以完成工作,具体字节流是怎么处理的,只是下一层协议需要处理的工作。
服务器
WSADATA wsaData;
sockaddr_in local;
local.sin_addr.s_addr=INADDR_ANY;
int wsaret=WSAStartup(0x101,&wsaData);
server=socket(AF_INET,SOCK_STREAM,0);
if(bind(server,(sockaddr*)&local,sizeof(local))!=0)
if(listen(server,10)!=0)
SOCKET client;
sockaddr_in from;
int fromlen=sizeof(from);
client=accept(server,(struct sockaddr*)&from,&fromlen);//使用另外一个随机端口与客户端端口通讯
send(client,buff,strlen(buff),0);
n=recv(client,buff,512,0);
closesocket(client);
closesocket(server);
WSACleanup();
客户端
WSADATA wsaData;
struct sockaddr_in sockAddr;
int wsaret=WSAStartup(0x101,&wsaData);
SOCKET clientSocket;
clientSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
sockAddr.sin_addr.s_addr = inet_addr(servername);
sockAddr.sin_family=AF_INET;
sockAddr.sin_port = htons((u_short)nHostPort);
int r = connect(clientSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr));
send(clientSocket,buff,strlen(buff),0);
z=recv(clientSocket,buff,512,0);
closesocket(clientSocket);
WSACleanup();
一些不常见的函数
ioctlsocket() 控制套接口的模式。
int PASCAL FAR ioctlsocket( SOCKET s, long cmd, u_long FAR* argp);
s:一个标识套接口的描述字。
cmd:对套接口s的操作命令。
argp:指向cmd命令所带参数的指针。
u_long PASCAL FAR htonl( u_long hostlong);
hostlong:主机字节顺序表达的32位数。
注释:
本函数将一个32位数从主机字节顺序转换成网络字节顺序。
u_short PASCAL FAR htons( u_short hostshort);
hostshort:主机字节顺序表达的16位数。
注释:
本函数将一个16位数从主机字节顺序转换成网络字节顺序。
u_long PASCAL FAR ntohl( u_long netlong);
netlong:一个以网络字节顺序表达的32位数。
注释:
本函数将一个32位数由网络字节顺序转换为主机字节顺序。
u_short PASCAL FAR ntohs( u_short netshort);
netshort:一个以网络字节顺序表达的16位数。
注释:
本函数将一个16位数由网络字节顺序转换为主机字节顺序。
udp分为主动和被动,如果主动接收,recv要阻塞,直到接收到数据,被动的话使用select函数,使得进行指定时间的等待后不论有无数据均返回.
udp通讯实例
#include <winsock2.h>
#include <stdio.h>
BOOL InitWinsock();
void main()
{
//调换///
// u_short hostshort1 = 8500;
// char * strIp1 = "192.168.1.125";
// u_short hostshort2 = 8501;
u_short hostshort2 = 8500;
u_short hostshort1 = 8501;
char * strIp1 = "192.168.1.82";
//客户端///
SOCKET socketClient;
InitWinsock();
socketClient=socket(AF_INET,SOCK_DGRAM,0);
//一下隐掉的部分可以不用。
// struct sockaddr_in localClient;
// localClient.sin_family=AF_INET;
// localClient.sin_port=htons(0); ///监听端口
// localClient.sin_addr.s_addr=INADDR_ANY; ///本机
//
// bind(socketClient,(struct sockaddr*)&localClient,sizeof localClient);
struct sockaddr_in server;
int len =sizeof(server);
server.sin_family=AF_INET;
server.sin_port=htons(hostshort1); ///server的监听端口
server.sin_addr.s_addr=inet_addr(strIp1); ///server的地址
服务端//
SOCKET socketServer;
InitWinsock();
struct sockaddr_in localServer;
localServer.sin_family=AF_INET;
localServer.sin_port=htons(hostshort2); ///监听端口
localServer.sin_addr.s_addr=INADDR_ANY; ///本机
socketServer=socket(AF_INET,SOCK_DGRAM,0);
bind(socketServer,(struct sockaddr*)&localServer,sizeof localServer);
struct sockaddr_in from;
int fromlen =sizeof(from);
while (1)
{
/Client 发送
char bufferClient[1024]="\0";
printf("input message\n");
scanf("%s",bufferClient);
if (strcmp(bufferClient,"bye")==0)
break;
if (sendto(socketClient,bufferClient,sizeof bufferClient,0,(struct sockaddr*)&server,len)!=SOCKET_ERROR)
{
// if (recvfrom(socketClient,bufferClient,sizeof bufferClient,0,(struct sockaddr*)&server,&len)!=SOCKET_ERROR)
// printf("rece from server:%s\n",bufferClient);
}
/服务端接收/
char bufferServer[1024]="\0";
printf("waiting for message from others-------------\n");
if (recvfrom(socketServer,bufferServer,sizeof bufferServer,0,(struct sockaddr*)&from,&fromlen)!=SOCKET_ERROR)
//if (recv(socketServer, bufferServer, sizeof bufferServer , 0)!=SOCKET_ERROR)
{
printf("Received datagram from %s--%s\n",inet_ntoa(from.sin_addr),bufferServer);
给cilent发信息
//sprintf(bufferServer,"Received datagram from sender.");
//sendto(socketServer,bufferServer,sizeof bufferServer,0,(struct sockaddr*)&from,fromlen);
}
//
Sleep(500);
}
closesocket(socketClient);
closesocket(socketServer);
}
BOOL InitWinsock()
{
int Error;
WORD VersionRequested;
WSADATA WsaData;
VersionRequested=MAKEWORD(2,2);
Error=WSAStartup(VersionRequested,&WsaData); //启动WinSock2
if(Error!=0)
{
return FALSE;
}
else
{
if(LOBYTE(WsaData.wVersion)!=2||HIBYTE(WsaData.wHighVersion)!=2)
{
WSACleanup();
return FALSE;
}
}
return TRUE;
}