Socket编程

Socket编程

1.客户端代码

//
// Created by zWX1143994 on 2023/4/14.
//

#include <iostream>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

int main()
{
    int client_socket = 0;
    struct sockaddr_in clent_addr;
    char buf[1024] = {};
    int recvSize = 0;

    client_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (client_socket < 0)
    {
        printf("socket Error: %s (errno: %d)\n", strerror(errno), errno);
        _exit(0);
    }

    memset(&clent_addr, 0, sizeof(clent_addr));
    clent_addr.sin_family = AF_INET;
    clent_addr.sin_port = htons(1234);
    clent_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    //inet_pton(AF_INET, SERVER_IP, &clent_addr.sin_addr);   //?
    if (connect(client_socket, (struct sockaddr*)&clent_addr, sizeof(clent_addr)) < 0)
    {
        printf("connect Error: %s (errno: %d)\n", strerror(errno), errno);
        _exit(0);
    }
    std::cout << "请输入信息:" << std::endl;
    while (1)
    {
        fgets(buf, sizeof(buf), stdin);
        //memset(&buf, 0, sizeof(buf));
        write(client_socket, buf, sizeof(buf));
        memset(&buf, 0, sizeof(buf));
        recvSize = read(client_socket, buf, sizeof(buf));
        if (recvSize == 0)
        {
            printf("Service is close!\n");
        }
        std::cout << "Service return Msg : " << buf << std::endl;

    }

    return 0;
}

2.服务端代码

//
// Created by zWX1143994 on 2023/3/30.
//
#include "stdio.h"
#include "string.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <iostream>


#define SERVER_IP   "127.0.0.1"
#define SERVER_PORT  1234
#define MAXSIZE  1024

int main(){

    int server_socket = 0;
    int clent_socket = 0;
    char buf[MAXSIZE] = {};
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int recvSize = 0;

    server_socket = socket(AF_INET,SOCK_STREAM,0);
    if (server_socket < 0)
    {
        printf("socket() ERROR: %s (errno: %d)\n", strerror(errno), errno);
        _exit(0);
    }
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_family = AF_INET;

    if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
    {
        printf("bind ERROR: %s (errno: %d)\n", strerror(errno), errno);
    }

    if (listen(server_socket,20) < 0)
    {
        printf("listen ERROR: %s (errno: %d)\n", strerror(errno), errno);
    }

    clent_socket = accept(server_socket, (struct sockaddr*)NULL, NULL);
    if (clent_socket < 0)
    {
        printf("accept Error: %s (errno: %d)\n", strerror(errno), errno);
    }
    while (1)
    {
        memset(&buf, 0, MAXSIZE);
        recvSize = read(clent_socket, buf, MAXSIZE);
        if (recvSize == 0)
        {
            printf("client is disconnected!\n");
            close(clent_socket);
            break;
        }
        printf("recvMsg : %s", buf);
        std::cin >> buf;
        write(clent_socket, buf, MAXSIZE);
        printf("Msg is send!\n");
    }

    close(clent_socket);
    close(server_socket);
}

3.Socket编程的基本流程

Socket编程需遵循的一个基本原则就是在进程通信之前,必须建立完整的相关。

两个进程间的通信链路称为连接。连接两端的进程分别可以用一个三元组标识,即

协议,本地地址,本地端口号),也被称为一个半相关(half-association),它描述了连接中的一端。

一个完整的连接可用一个五元组协议,本地地址,本地端口号,远地地址,远地端口号)标识,该五元组也称为一个全相关。协议是连接中两个进程需要共同遵守的协议。

4.Socket编程的基本函数

4.1 socket接口函数

在这里插入图片描述

4.2 bind接口函数

在这里插入图片描述

4.3 connect接口函数

在这里插入图片描述

4.4 listen接口函数

在这里插入图片描述

4.5 accept接口函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ab3MdjWA-1682070908963)(D:\zwl\文档笔记\C++\Socket图片\image-20230421173532164.png)]

4.6 send函数和write函数

在这里插入图片描述
在这里插入图片描述

4.7 recv函数和read函数

在这里插入图片描述
在这里插入图片描述

5.Socket编程基本步骤

服务器端编程的步骤:

1:创建套接字(socket());
2:绑定套接字到一个IP地址和一个端口上(bind());
3:将套接字设置为监听模式等待连接请求(listen());
4:请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept());
5:用返回的套接字和客户端进行通信(send()/recv());
6:关闭套接字(closesocket)。

**客户端编程的步骤:
** 1:加载套接字库,创建套接字(socket());
2:向服务器发出连接请求(connect());
3:和服务器端进行通信(send()/recv());
4:关闭套接字,关闭加载的套接字库(closesocket())。

6. Socket基本类型简介

1.struct sockaddr结构:

struct sockaddr 
{                   
    unsigned short sa_family; /* 地址族, AF_xxx */                    
    char sa_data[14]; /* 14 字节的协议地址 */ 
};

sa_family是地址家族,是“AF_xxx”的形式。常设为“AF_INET”,代表Internet(TCP/IP)地址族。sa_data则包含该socket的IP地址和端口号。 该结构的缺陷在于IP地址与端口号混合在一起。

2.sockaddr_in结构:

struct sockaddr_in 
{      
    short int sin_family; /* 地址族 */      
    unsigned short int sin_port; /* 端口号 */     
    struct in_addr sin_addr; /* IP地址 */     
    unsigned char sin_zero[8]; /* 填充0 以保持与struct sockaddr同样大小 */ 
};

3.sockaddr 和 sockaddr_in的相互关系

一般先把sockaddr_in变量赋值后,强制类型转换后传入用sockaddr做参数的函数

sockaddr_in用于socket定义和赋值

sockaddr用于函数参数

in_addr sin_addr; /* IP地址 /  
unsigned char sin_zero[8]; /
填充0 以保持与struct sockaddr同样大小 */
};


### 3.sockaddr 和 sockaddr_in的相互关系
 一般先把sockaddr_in变量赋值后,强制类型转换后传入用sockaddr做参数的函数

 **sockaddr_in**用于socket定义和赋值

 **sockaddr**用于函数参数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一个简单的socket网络编程例子: 服务器代码: #include #include #include #include #pragma comment(lib,"ws2_32.lib") //这句话的意思是加载ws2_32.lib这个静态库 #define NETWORK_EVENT WM_USER+100 //如果你用mfc做开发,你可以点击菜单project-〉setting-〉link-〉object/library中添加这个静态库。 //如果你用c语言,你需要通过#pragma comment(命令来连接静态库 int main(int argc, char* argv[]){ HANDLE hThread = NULL; //判断是否输入了端口号 if(argc!=3){ printf("Usage: %sPortNumber\n",argv[1]); exit(-1); } //把端口号转化成整数 short port; if((port = atoi(argv[2]))==0){ printf("端口号有误!"); exit(-1); } WSADATA wsa; //初始化套接字DLL if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){ //高字节指定了次版本号,低字节指定了主版本号,两个字节加到一起,就是你想要的Winsock库的版本号了 printf("套接字初始化失败!"); exit(-1); } //创建套接字 SOCKET serverSocket; if((serverSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){ printf("创建套接字失败!"); exit(-1); } struct sockaddr_in serverAddress; memset(&serverAddress,0,sizeof(sockaddr_in)); serverAddress.sin_family=AF_INET; serverAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY); serverAddress.sin_port = htons(port); //绑定 if(bind(serverSocket,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR){ printf("套接字绑定到端口失败!端口: %d\n",port); exit(-1); } //进入侦听状态 if(listen(serverSocket,SOMAXCONN)==SOCKET_ERROR){ printf("侦听失败!"); exit(-1); } printf("Server %d is listening......\n",port); SOCKET clientSocket[5],maxSocket;//用来和客户端通信的套接字 struct sockaddr_in clientAddress;//用来和客户端通信的套接字地址 memset(&clientAddress,0,sizeof(clientAddress)); int addrlen = sizeof(clientAddress); fd_set fd_read; int i=0; int j; char buf[4096]; char buff[4096]="exit"; while(1) { FD_ZERO(&fd_read); maxSocket=serverSocket; FD_SET(serverSocket,&fd_read); //FD_SET(clientSocket[i-1],&fd_read); for(j=0;j<i;j++) { FD_SET(clientSocket[j],&fd_read); if(maxSocket"); //gets(buff); if(select(maxSocket+1,&fd_read,NULL,NULL,NULL)>0) { if(FD_ISSET(serverSocket,&fd_read)) { if(buff=="") { if((clientSocket[i++]=accept(serverSocket,(sockaddr*)&clientAddress,&addrlen))==INVALID_SOCKET) { printf("接受客户端连接失败!"); exit(-1); } else { for(j=0;j5) { printf("超过最大客户端数"); exit(-1); } } else { int bytes; for(int k=0;k<i;k++) { if(FD_ISSET(clientSocket[k],&fd_read)) { bytes=recv(clientSocket[k],buf,sizeof(buf),0); if(bytes==-1) { //listen(serverSocket,SOMAXCONN); for (int l=k;l<i;l++) clientSocket[l]=clientSocket[l+1]; i--; } /*if(bytes==0) { //printf("fdsdf"); listen(serverSocket,SOMAXCONN); for (int l=k;l0) { buf[bytes]='\0'; printf("Message from %s: %s\n",inet_ntoa(clientAddress.sin_addr),buf); if(send(clientSocket[k],buf,bytes,0)==SOCKET_ERROR) { printf("发送数据失败!"); exit(-1); } } } } } } } //清理套接字占用的资源 WSACleanup(); return 0; } 客户端代码: #include #include #include #pragma comment(lib,"ws2_32.lib") int main(int argc, char* argv[]){ //判断是否输入了IP地址和端口号 if(argc!=4){ printf("Usage: %s IPAddress PortNumber\n",argv[1]); exit(-1); } //把字符串的IP地址转化为u_long unsigned long ip; if((ip=inet_addr(argv[2]))==INADDR_NONE){ printf("不合法的IP地址:%s",argv[1]); exit(-1); } //把端口号转化成整数 short port; if((port = atoi(argv[3]))==0){ printf("端口号有误!"); exit(-1); } printf("Connecting to %s:%d......\n",inet_ntoa(*(in_addr*)&ip),port); WSADATA wsa; //初始化套接字DLL if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){ printf("套接字初始化失败!"); exit(-1); } //创建套接字 SOCKET sock,serverSocket; if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){ printf("创建套接字失败!"); exit(-1); } struct sockaddr_in serverAddress; memset(&serverAddress,0,sizeof(sockaddr_in)); serverAddress.sin_family=AF_INET; serverAddress.sin_addr.S_un.S_addr = ip; serverAddress.sin_port = htons(port); //建立和服务器的连接 if(connect(sock,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR) { printf("建立连接失败!"); exit(-1); } char buf[4096]; while(1){ printf(">"); //从控制台读取一行数据 gets(buf); if(send(sock,buf,strlen(buf),0)==SOCKET_ERROR){ printf("发送c数据失败!"); exit(-1); } int bytes; if((bytes=recv(sock,buf,sizeof(buf),0))==SOCKET_ERROR) { printf("接收c数据失败!\n"); exit(-1); } else { buf[bytes]='\0'; printf("Message from %s: %s\n",inet_ntoa(serverAddress.sin_addr),buf); } } //清理套接字占用的资源 WSACleanup(); return 0; }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值