Introduction to socket network programming

network programming

The behavior of exchanging data between two or more computers that have been networked is network programming. The
operating system we use every day has provided us with sockets, and we
can master network programming without being familiar with the principles of network data transmission.


What is the difference between socket in windows and socket in Linux?

  • same
  • LinuxIt is usually 文件描述符used to indicate or distinguish files that have been opened;
  • windows文件句柄Represented by the way, and the above is Linuxa 文件描述符similar concept;
  • different
  • LinuxEverything is a file, so a network connection is also a file.
  • WindowsIt will be socketdistinguished from the file, so the data transfer function is designed in a targeted manner Windows.socket

socket type

  • SOCK_STREAM

面向连接的套接字(Stream Sockets), is SOCK_STREAMthe right explanation. The protocol
is used TCPand has its own error correction mechanism. The protocol
used by the browser httpis based on面向连接的套接字

  • SOCK_DGRAM

无连接的套接字(Datagram Sockets), also called 数据报格式套接字.
Its transmission efficiency is relatively SOCK_STREAMhigh, but the work of verifying data is less.
Video chat and voice video are mostly used 无连接套接字to transmit data.

  • SOCK_RAW

原始套接字(raw-protocol interface).The
complete header of the data packet is saved IP, and the data can be analyzed through it.
Network security products usually use this type, such as MACaddress scanners, network sniffers and other products.


TCP socket

  • Server
#include <iostream>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

using namespace std;
int main()
{
    //初始化套接字库
    WORD wVersion;
    WSADATA wsaData;
    int err;
    wVersion = MAKEWORD(1, 1);
    err = WSAStartup(wVersion, &wsaData);
    //检查
    if (err != 0)
    {
        return err;
    }
    if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
    {
        //清理套接字库
        WSACleanup();
        return -1;
    }
    //创建套接字
    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, 10);

    cout << "server start at prot: 6000" << endl;
    SOCKADDR addrCli;
    int len = sizeof(SOCKADDR);
    char recvBuf[100];
    char sendBuf[100];
    while (true)
    {
        //接受连接请求
        SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrCli, &len);

        sprintf_s(sendBuf,100, "hello");

        send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);
        //接受或发送数据
        recv(sockConn, recvBuf, 100, 0);

        std::cout << recvBuf << std::endl;

        //关闭套接字
        closesocket(sockConn);
    }

    //关闭套接字
    closesocket(sockSrv);
    //清理套接字库
    WSACleanup();

    system("pause");
    return 0;
}
  • client
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main()
{
    //初始化套接字库
    WORD wVersion;
    WSADATA wsaData;
    int err;
    wVersion = MAKEWORD(1, 1);
    err = WSAStartup(wVersion, &wsaData);
    //检查
    if (err != 0)
    {
        return err;
    }
    if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
    {
        //清理套接字库
        WSACleanup();
        return -1;
    }

    //创建tcp套接字
    SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.0.131");
    //addrSrv.sin_addr.S_un.S_addr = htons(6000);//大失误
    addrSrv.sin_port = htons(6000);
    addrSrv.sin_family = AF_INET;

    //连接服务器
    connect(sockCli, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

    char sendBuf[] = "world";
    char recvBuf[100];

    //发送数据到服务器
    send(sockCli, sendBuf, strlen(sendBuf) + 1, 0);

    //接收服务器发送的数据
    recv(sockCli, recvBuf, sizeof(recvBuf), 0);

    cout << recvBuf << endl;

    closesocket(sockCli);

    WSACleanup();

	system("pause");
	return 0;
}

UDP socket

  • Server
#include <iostream>
#include <WinSock2.h>

#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main()
{
    //初始化套接字库
    WORD wVersion;
    WSADATA wsaData;
    wVersion = MAKEWORD(1, 1);
    int err = WSAStartup(wVersion, &wsaData);
    //检查
    if (err != 0)
    {
        cout << WSAGetLastError() << endl;
        return err;
    }
    if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
    {
        cout << WSAGetLastError() << endl;
        WSACleanup();
        return -1;
    }

    //创建套接字
    SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    addrSrv.sin_port = htons(6002);//主机字节序转换
    addrSrv.sin_family = AF_INET;

    //绑定到本机6002端口
    bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

    //接受请求,处理请求
    SOCKADDR_IN addrCli;
    int len = sizeof(SOCKADDR);

    char sendBuf[] = "UDP Server ...";
    char recvBuf[100];

    cout << "Start UDP Server with port 6002 " << endl;;
    while (true)
    {
        //接收数据
        recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR*)&addrCli, &len);
        cout << "Recv: " << recvBuf << endl;

        //发送数据
        sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrCli, len);
        cout << "Send: " << sendBuf << endl;
    }

    //关闭套接字并清除套接字库
    closesocket(sockSrv);
    WSACleanup();

    system("pause");
    return 0;
}
  • client
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
#include <WinSock2.h>

#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main()
{
    //初始化套接字库
    WORD wVersion;
    WSADATA wsaData;
    wVersion = MAKEWORD(1, 1);
    int err = WSAStartup(wVersion, &wsaData);
    //检查
    if (err != 0)
    {
        return err;
    }
    if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
    {
        WSACleanup();
        return -1;
    }

    //创建UDP套接字
    SOCKET sockCli = socket(AF_INET, SOCK_DGRAM, 0);
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addrSrv.sin_port = htons(6002);
    addrSrv.sin_family = AF_INET;

    SOCKADDR_IN addrCli;
    int len = sizeof(SOCKADDR);

    char sendBuf[] = "send from UDP client ...";
    char recvBuf[100];

    //发送数据到服务端并打印
    cout << "send to server: " << sendBuf << endl;
    sendto(sockCli, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrSrv, len);

    //接收服务端数据并打印
    recvfrom(sockCli, recvBuf, 100, 0, (SOCKADDR*)&addrCli, &len);
    cout << "receve from: " << recvBuf << endl;

    //关闭套接字并清除套接字库
    closesocket(sockCli);
    WSACleanup();

    system("pause");
    return 0;
}

Analysis of common functions

  • WSAStartup() function

It is Windowsa function specific to the operating system. When using network programming in the system, it is necessary to load
the dynamic link library. Before using this function, it is necessary to call the function to initialize the dynamic library.Windowsws2_32.dll
dllWSAStartup()

Function prototype:

int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
  • socket() function

The program uses socketa function to create a socket, whether it is Linuxor Windowsis the same, the difference is that the return value is different. The return value of the function
Linuxin the middle is , and the return value in the middle is . The environment I am practicing here is , so the code examples here are subject to .socketintWindowsSOCKET
windowsWindows

Function prototype:

SOCKET socket(int af, int type, int protocol);
  • bind() function

After creating the socket, you need to determine various attributes of the socket, such as IPaddress, port and other information.
These information are sockaddrstored in a structure variable.

Function prototype:

int bind(SOCKET sock, const struct sockaddr *addr, int addrlen); 
  • connect() function

It is used by the client to establish a connection after creating a socket.
Its parameters are bindthe same as

Function prototype:

int connect(SOCKET sock, const struct sockaddr *serv_addr, int addrlen);
  • listen() function

After the server binds the socket, it also uses listenthe function to make the socket enter the passive listening state.
The second parameter is the maximum length of the request queue.

Function prototype:

int listen(SOCKET sock, int backlog);
  • accept() function

After the socket listenenters the passive listening state through the function, acceptit receives the client request through the function.
Its parameters are the same listenas connectthe function.

Function prototype:

SOCKET accept(SOCKET sock, struct sockaddr *addr, int *addrlen);
  • send() function

The purpose of the above series of connections is naturally to realize the sending and receiving of data between the server and the client. The
sendfunction is to send data from the server, and the fourth parameter can refer to the flags parameter in the send recv function

Function prototype:

int send(SOCKET sock, const char *buf, int len, int flags);
  • recv() function

recvThe function of the function is to receive data from the server or client.
It sendis the same as the parameter of the function.

Function prototype:

int recv(SOCKET sock, char *buf, int len, int flags);

Summarize

This blog content simply covers socketthe functions needed for programming,
and gives simple sample codes. socketIt is still helpful for getting started with programming.\

WindowsThe socket functions extended by the operating system generally WSAstart with, which means Windows socket API. Commonly used ones such as:
WSASend, WSARecvand the ones mentioned above WSACleanup.

Guess you like

Origin blog.csdn.net/Stephen8848/article/details/124773426