基本的 TCP Socket 编程(c++、linux环境下)

        本文简要介绍并实现一个客户端和服务器之间进行通信的程序,主要目的是为了了解建立客户端和服务器连接的过程,熟悉相应的API。

主要用到的API有如下几个,socket()、connect()、bind()、listen()、accept()。

下面附一个简单的代码实现:

首先,是客户端程序:

#include <sys/socket.h>
#include <netinet/in.h>
#include <memory.h>
#include <arpa/inet.h>
#include <unistd.h>

#include <iostream>

using namespace std;


int RunClient(int ServerPort, const char *strServerIP)
{
    //根据指定的协议和套接字类型来获取客户端套接字
    int ClientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == ClientSocket)   //-1表示获取失败,返回并输出错误原因
    {
	cout << "get clientsocket error" << endl;
	return -1;
    }

    //创建链接服务器所需要的信息
    sockaddr_in ServerAddress;    //定义一个套接口的地址对象,其本身是一个结构体,存贮服务器的端口、协议、地址长度、ip等信息
    memset(&ServerAddress, 0, sizeof(sockaddr_in));     //将该地址对象所占用的内存空间清零
    ServerAddress.sin_family = AF_INET;   //对套接口地址对象中的字段赋值,协议与socket中一致
    ServerAddress.sin_port = htons(ServerPort);    //对端口字段进行赋值
    int writeip = inet_pton(AF_INET, strServerIP, &ServerAddress.sin_addr); // 将服务器的ip地址存储到地址字段中
    if(writeip != 1)     //不等于一则说明存贮失败,打印错误信息,关闭客户端套接字并返回
    {
	cout << "inet_pton store ip error" << endl;
	close(ClientSocket);
	return -1;
    }

    cout << "prepare to connect server....." << endl;

    //创建本地客户端套接字与网络服务器的链接
    int conn = connect(ClientSocket, (sockaddr*)&ServerAddress, sizeof(ServerAddress));
    if(conn == -1)           //返回-1表示链接失败,关闭客户端套接字并返回错误信息
    {
	cout << "connect error" << endl;
	close(ClientSocket);
	return -1;
    }
    else
    {
        cout << "connect server success! " << endl;
    }
    
    //链接成功后,则读取从服务器返回的信息,并存入缓冲区中
    char buf[13];
    read(ClientSocket, buf, 11);
    cout << "the info from server is:"<< endl;
    cout << buf << endl;        //打印服务器返回的信息
    
    //完成信息传输后,关闭客户端套接字
    close(ClientSocket);

    cout << "client closed" << endl;

    return 0;
}



int main()
{
    RunClient(4000, "127.0.0.1");

    return 0;
}

接着是服务器端程序:

#include <netinet/in.h>
#include <arpa/inet.h>
#include <memory.h>
#include <unistd.h>

#include <iostream>

using namespace std;


int RunServer(int Port, int LengthOfQueueOfListen = 100, const char *strBoundIP = NULL)
{
    //创建一个用来监听的套接口
    int ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == ListenSocket)                 //失败返回-1
    {
	cout << " creat listensocket error" << endl;
	return -1;
    }
    
    
    //设置监听套接口的地址配置信息
    sockaddr_in ServerAddress;     //定义一个套接口的地址对象
    memset(&ServerAddress, 0, sizeof(sockaddr_in));  //该对象所占用内存区域清零
    ServerAddress.sin_family = AF_INET;    //协议字段赋值
    ServerAddress.sin_port = htons(Port);  //端口
    if(NULL == strBoundIP)     //如果没有指定服务器绑定的ip,则监听本机的所有ip (多网卡时可能有多个ip)
    {
	ServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    }
    else
    {   //否则就使用指定的ip,将其写入到套接口的ip字段
	int boundip = inet_pton(AF_INET, strBoundIP, &ServerAddress.sin_addr);
	if(boundip != 1)           //写入失败则返回错误,并关闭监听套接口
	{
	    cout << "inet_pton error" << endl;
	    close(ListenSocket);
	    return -1;
	}
    }

   
    //将监听套接口与其套接口地址信息绑定
    int bindd = bind(ListenSocket, (sockaddr *)&ServerAddress, sizeof(sockaddr_in));
    if(bindd == -1)                 //绑定失败返回错误信息,关闭监听套接口
    {
	cout << "bind error" << endl;
	close(ListenSocket);
	return -1;
    }

    //listen将监听套接口从主动转为被动状态,指示内核应该接收指向该套接口的链接请求,第二个参数表示最大连接个数
    int lis = listen(ListenSocket, LengthOfQueueOfListen);   
    if(lis == -1)             //监听失败返回错误信息,关闭监听套接字
    {
	cout << "listen error" << endl;
	close(ListenSocket);
	return -1;
    }
    
    //从连接的队列中,取出一个已完成的连接,并保存这个连接对应的客户端信息(ip、端口、协议等)
    sockaddr_in ClientAddress;   //创建套接口对象,主要用于存贮客户端的套接字信息
    socklen_t LengthOfClientAddress = sizeof(sockaddr_in);
    cout << "prepare to connect client....." << endl;
    //进行连接,并存贮连接到的客户端套接口信息,若连接成功则会返回一个表示已经连接的套接口,用来进行信息传输
    int ConnectedSocket = accept(ListenSocket, (sockaddr *)&ClientAddress, &LengthOfClientAddress);  
    if(-1 == ConnectedSocket)    //若连接失败,则返回失败信息,关闭监听套接字
    {
	cout << "accept error" << endl;
	close(ListenSocket);
	return -1;
    }
    else
    {
        cout << "connect client success!" << endl;
    }

    //根据表示已经连接的套接口,向客户端发送信息
    write(ConnectedSocket, "Hello World", 11);
    cout << "the info return to client is:\r\nHello World"<< endl;

    //关闭表示已经连接的套接口以及监听套接口
    close(ConnectedSocket);
    close(ListenSocket);
    cout << "server closed \r\n";
    return 0;
}


int main()
{
    RunServer(4000);
    return 0;
}

 编译运行之后,得到的结果如下所示:

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页