由于不同的计算机存放数据字节的顺序不同,这样发送方发送数据后,即使接收方接收到该数据,也有可能无法查看所接收到的数据。所以在网络中不同主机间进行通信时,要统一采用网络字节顺序。
客户机/服务器模式在操作过程中采取的是主动请求的方式。首先服务器方要先启动,并根据请求提供相应的服务:
①打开一个通信信道并告知本地主机,它愿意在某一地址和端口接收客户请求。
②等待客户请求到达端口。
③接收到重复服务请求,处理该请求并发送应答信号。接收到并发服务器请求,要激活一个新的进程来处理这个客户请求。新进程处理此客户请求,并不需要对其他请求作出应答。服务完成以后,关闭此新进程与可与的通信链路,并终止。
④返回第二步,等待另一客户请求
⑤关闭服务器。
而客户方:
①打开一个通信信道,并连接到服务器所在主机的特定端口。
②向服务器发送服务请求报文,等待并接收应答;继续提出请求。
③请求结束后关闭通信通道并终止。
套接字的类型:
流式套接字(SOCK_STREAM——IP)
数据报式套接字(SOCK_DGRAM——TCP)
原始套接字(SOCK_RAW)
基于TCP的socket编程:
服务器端:
①创建套接字(socket)
②将套接字绑定到一个本地地址和端口上(bind)
③将套接字设为监听模式,准备接收客户端请求(listen)
④等待客户请求到来;当请求到来后,接收连接请求,返回一个新的对应于此连接的套接字(accept)
⑤用返回的套接字和客户端进行通信(send/recv)
⑥返回,等待另一客户请求
⑦关闭套接字
客户端:
①创建套接字(socket
②向服务器发出连接请求(connect)
③和服务器端进行通信(send/recv)
④关闭套接字
基于UDP的socket编程
服务器端:
①创建套接字(socket)
②将套接字绑定到一个本地地址和端口上(bind)
③等待接收数据(recvfrom)
④关闭套接字
客户端:
①创建套接字(socket)
②向服务器发送数据(sendto)
③关闭套接字
加载套接字字库WSAStartup、WSAClearUp
socket函数:
SOCKET socket( int af , int type, int protocol);如果调用成功则返回一个新的SOCKET数据类型的套接字描述符;如果调用失败,这个函数就会返回一个INVALID_SOCKET值,错误信息可以通过WSAGetLastError函数返回。
bind函数:
int bind( SOCKET s, const struct sockaddr FAR* name, int namelen);
inet_addr和inet_ntoa函数:
inet_addr函数将点分十进制转换为一个合适分配给S_addr的u_long类型的数值,inet_ntoa函数完成相反的工作。
int listen( SOCKET s, int backlog);
SOCKET accpet( SOCKET s, struct sockaddr *addr, int addrlen);
int send(SOCKET s, const char buf, int len , int flags);
int recv(SOCKET s, char *buf , int len , int flags);
int connect(SOCKET s, const struct sockaddr *name, int namelen);
int recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr*from , int fromlen);
int sendto(SOCKET s, const char *buf, int len, int flags, const struct sockadd *to, int tolen);
htons和htonl函数:
Window Sockets的htons函数将把一个u_short类型的值从主机字节顺序转换为TCP/IP网络字节顺序。htonl把一个u_long类型的值从主机字节顺序转换为TCP/IP网络字节顺序。
基于TCP的服务器端:
#include <Winsock2.h>
#include<stdio.h>
#include <string.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( true )
{
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);
}
}
基于TCP的客户机端:
#include <Winsock2.h>
#include<stdio.h>
#include <string.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 lalor", strlen("This is lalor") + 1, 0);
closesocket(sockClient);
WSACleanup();
return;
}
基于UDP的服务器端:
#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_DGRAM, 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));
char recvBuf[100];
char sendBuf[100];
char tempBuf[200];
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
while(1)
{
recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR*)&addrClient, &len);
if( strcmp( "exit" , recvBuf) == 0 )
{
sendto( sockSrv, "exit", strlen("exit") + 1, 0, (SOCKADDR*)&addrClient, len);
printf("chat end\n");
break;
}
sprintf(tempBuf, "%s say: %s" , inet_ntoa(addrClient.sin_addr), recvBuf);
printf("%s\n", tempBuf);
printf("Please input data:\n");
gets(sendBuf);
sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrClient, len);
}
closesocket(sockSrv);
WSACleanup();
}
基于UDP的客户端:
#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_DGRAM, 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);
char recvBuf[100];
char sendBuf[100];
char tempBuf[100];
int len = sizeof(SOCKADDR);
while(1)
{
printf("Please input data:\n");
gets(sendBuf);
sendto( sockClient, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrSrv, len);
recvfrom(sockClient, recvBuf, 100, 0, (SOCKADDR*)&addrSrv, &len);
if( strcmp("exit" , recvBuf) == 0 )
{
sendto(sockClient, "exit" , strlen("exit" + 1), 0, (SOCKADDR*)&addrSrv, len);
printf("Chat end\n");
break;
}
sprintf(tempBuf, "%s say: %s", inet_ntoa(addrSrv.sin_addr), recvBuf);
printf("%s\n" , tempBuf);
}
closesocket(sockClient);
WSACleanup();
}
vc++深入详解之第十四章网络编程笔记
最新推荐文章于 2025-09-08 22:18:39 发布
