客户端与服务器之间分别通过TCP和UDP进行通信

一:TCP/IP协议的应用一般采用客户/服务器模式,因此在实际应用中,必须有客户和服务器两个进程,并且首先启动服务器,其系统调用时序图如下。 面向连接的协议(如TCP)的套接字系统调用如图2.1所示:

注意:服务器必须首先启动,直到它执行完accept()调用,进入等待状态后,方能接收客户请求。假如客户在此前启动,则connect()将返回出错代码,连接不成功。


这里直接上C++代码:

客户端代码如下所示:

#include <iostream>
#include <winsock2.h>
using namespace std;
#pragma comment(lib, "ws2_32.lib")

int main()
{
//1.定位档次--- 加载库【这一步不用看,可以在帮助文档中直接查WSAStartup()函数,然后复制粘贴实例
   WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD(2, 2);
    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0) {
        printf("WSAStartup failed with error: %d\n", err);
        return 1;
    }

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        printf("Could not find a usable version of Winsock.dll\n");
        WSACleanup();
        return 1;
    }
    else
        printf("The Winsock 2.2 dll was found okay\n");

//2.-- socket--套接字
SOCKET sock = socket(AF_INET,SOCK_STREAM ,IPPROTO_TCP);
if( INVALID_SOCKET  == sock)
{
 WSACleanup();
          return 1;
}

//3. Connect
sockaddr_in address;
address.sin_family=AF_INET;
address.sin_port=htons(1234);//将主机端口号改为网络字节序//-------------------关于网络字节序推荐看博客http://blog.csdn.net/hguisu/article/details/7449955#t1
address.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//将字符串地址转为网络字节序

if(SOCKET_ERROR == connect(sock,(const sockaddr*)&address,sizeof(address)))
{
cout<<"Connect Failed!!!!"<<endl;
}

char buffer[1024]={0};
cin>>buffer;
int n=send(sock,buffer,sizeof(buffer),0);
if(n>0)
{
int n1=recv(sock,buffer,sizeof(buffer),0);
if(n1>0)
cout<<buffer<<endl;
}

closesocket(sock);
WSACleanup();

system("pause");
return 0;
}

服务器代码如下:

#include <iostream>
#include <winsock2.h>
using namespace std;

#pragma comment(lib, "ws2_32.lib")

int main()
{
//1.定位档次--- 加载库
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD(2, 2);
    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0) {
        printf("WSAStartup failed with error: %d\n", err);
        return 1;
    }

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
    
        printf("Could not find a usable version of Winsock.dll\n");
        WSACleanup();
        return 1;
    }
    else
        printf("The Winsock 2.2 dll was found okay\n");

//2.socket--套接字(相当于应用程序与外界进行通信的接口)
SOCKET sockListener = socket(AF_INET,SOCK_STREAM ,IPPROTO_TCP);
if( INVALID_SOCKET  == sockListener)
{
 WSACleanup();
          return 1;
}

//3.选址 ---绑定(ip,端口号)
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(1234);
addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");

if(SOCKET_ERROR == bind(sockListener,(const sockaddr*)&addr,sizeof(addr)))
{
closesocket(sockListener);
WSACleanup();
system("pause");
         return 1;
}

//4.监听,通知TCP,服务器准备好接收连接
if(SOCKET_ERROR == listen(sockListener,10))
{
closesocket(sockListener);
WSACleanup();
         return 1;
}
//5.accept()接收链接
SOCKET sockWaiter= accept(sockListener,NULL,NULL);
if(INVALID_SOCKET == sockWaiter)
{
cout<<"Socket Failed!!"<<endl;
}

char buffer[1024]={0};
int n=recv(sockWaiter,buffer,sizeof(buffer),0);
if(n>0)
{
cout<<buffer<<endl;
cin>>buffer;
send(sockWaiter,buffer,sizeof(buffer),0);
}

//7.关闭
closesocket(sockWaiter);
closesocket(sockListener);
//8.关店(关闭加载器)
WSACleanup();

system("pause");
return 0;
}

二: 无连接协议(UDP)的套接字调用如图2.2所示


无连接服务器也必须先启动,否则客户请求传不到服务进程。无连接客户不调用connect()。因此在数据发送之前,客户与服务器之间尚未建立完全相关,但各自通过socket()bind()建立了半相关。发送数据时,发送方除指定本地套接字号外,还需指定接收方套接字号,从而在数据收发过程中动态地建立了全相关。 

下面是客户端代码

#include<iostream>
#include <winsock2.h>
//#include"string.h"
using namespace std;
#pragma comment(lib, "ws2_32.lib")


int main()
{
//1.定位档次  : 哪个版本
   WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD(2, 2);
    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0) {
        printf("WSAStartup failed with error: %d\n", err);
        return 1;
    }
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        printf("Could not find a usable version of Winsock.dll\n");
        WSACleanup();
        return 1;
    }
    else
        printf("The Winsock 2.2 dll was found okay\n");

//2.创建socket套接字,socket相当于进程的接口,用于与外界进行通信  
SOCKET mysocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);

if(INVALID_SOCKET ==mysocket)
{
  WSACleanup();
           return 1;


struct sockaddr_in address;
address.sin_family=AF_INET;
address.sin_port=htons(1234);
address.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
//address.sin_addr.S_un.S_addr=inet_addr("#.#.#.255");//UDP数据报的直接广播:将数据传播到指定网段内
//address.sin_addr.S_un.S_addr=inet_addr("255.255.255.255");//UDP数据报的有限广播:将数据传播到本局域网内所有网段
//广播形式时,得添加下面操作:  设置广播类型setsockopt()
BOOL bflag=true;
setsockopt(mysocket,SOL_SOCKET,SO_BROADCAST,(const char*)bflag,sizeof(bflag));

char buff[1024]={0};
//可以添加while循环,一直发送
while (1)
{
cin>>buff;
sendto(mysocket,buff,sizeof(buff),0,(const sockaddr*)&address,sizeof(address));
}

system("pause");
return 0;
}

服务器端代码如下:

#include<iostream>
#include <winsock2.h>

using namespace std;
#pragma comment(lib, "ws2_32.lib")

int main()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD(2, 2);
    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0) {
        printf("WSAStartup failed with error: %d\n", err);
        return 1;
    }

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        printf("Could not find a usable version of Winsock.dll\n");
        WSACleanup();
        return 1;
    }
    else
        printf("The Winsock 2.2 dll was found okay\n");
      
//2.socket套接字
SOCKET mysocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);

if(INVALID_SOCKET ==mysocket)
{
  WSACleanup();
       return 1;
}

/*通过函数获取IP地址*/
//char name[100];
//gethostname(name,sizeof(name));
//hostent* h=gethostname(name);

//3.地址绑定
struct sockaddr_in address;
address.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
address.sin_family=AF_INET;//表示使用IPV4
address.sin_port=htons(1234);
int bn=bind(mysocket,(sockaddr*)&address,sizeof(address));
if(bn>0)
{
closesocket(mysocket);
WSACleanup();
                return 1;
}

//创建socket时有两个属性:阻塞态(默认)和非阻塞态===改变阻塞状态是通过函数
char buff[1024]={0};

//定义结构体来接收Client地址信息
sockaddr_in fromAddress; 
int nSize=sizeof(fromAddress);

while(1){
if(SOCKET_ERROR == recvfrom(mysocket,buff,sizeof(buff),0,(sockaddr*)&fromAddress,&nSize))
{
closesocket(mysocket);
WSACleanup();
return 1;
}
//将地址转为int转为sting
cout<<inet_ntoa(fromAddress.sin_addr)<<endl;
cout<<buff;
}

closesocket(mysocket);
WSACleanup();

system("pause");
return 0;
}


  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值