linux socket网络编程基础知识

发布时间:2024年01月10日

整体设计: 在客户端,输入小写字母,服务器返回大写字母。

服务器就是本机,(本地服务器),用127.0.0.1测试。

?

本节对应视频:B站 C++就业班28_哔哩哔哩_bilibili

?1. 服务器端代码

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include<netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>    //最后这个是toupper  转换为大写字母的
int main() {
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sfd <0){
        printf("socket fun error/n");
        return -1;
    }

    //定义一个地址结gou体   
    struct sockaddr_in myad;
    //清空  memory
    bzero(&myad, sizeof(myad));
    myad.sin_family =AF_INET;
    myad.sin_port =htons(8888);
    myad.sin_addr.s_addr = htonl (INADDR_ANY);

    int ret = bind(sfd, (struct sockaddr *)&myad, sizeof(myad));
    if (ret<0) {
        printf("bind error/n");
        return -1;
    }

    //将socket从主动变为被动(服务器必备),这样可以监听来自客户的请求
    listen( sfd,128);   //后面数字随笔写?

    int newfd= accept(sfd,NULL,NULL); 
    //为什么传null 因为从谁来的,还不知道,一会儿改写,让这个函数能打印客户端ip地址 
    if (newfd <0) {
	printf("服务端,accept error、\n");
        return -1;
    }
    // printf("服务器端,get connect:%s\n",inet_ntoa(c_addr.sin_addr));
//把客户端发送过来的数据读出来
   int i =0;
   int n =0;
   char buf[1024];

    while (1 ){
        memset(buf,0x00,sizeof(buf));
        n = read (newfd,buf,sizeof(buf));
        if (n<=0){
            printf("客户端已关闭,或者读到的字符为0/n");
	    break;
        }
        for (i=0;i<n;i++){
            buf[i] =toupper(buf[i]);
        }

        printf("服务器端。客户端的数据变成大写了\n");
    //把数据传回客户端,变成大写了已经
        write (newfd, buf, n);
    }

    close(newfd);
    close(sfd);
return 0;
}

2.客户端代码

2.1 不能打印客户端地址
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include<netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main() {
    int sfd2 = socket(AF_INET, SOCK_STREAM, 0);
    if (sfd2 <0){
        printf("socket fun error/n");
        return -1;
    }
    //定义一个地址结gou体,服务器地址。
    struct sockaddr_in seradd;
    //清空  memory
    bzero(&seradd, sizeof(seradd));
    seradd.sin_family =AF_INET;
    seradd.sin_port = htons(8888);
   
    int s = inet_pton( AF_INET,"127.0.0.1",&seradd.sin_addr.s_addr);
    if (s <= 0) {
        if (s == 0)
            fprintf(stderr, "Not in presentation format");
        else
            perror("inet_pton");
        exit(EXIT_FAILURE);
    }

    int ret333 = connect(sfd2,(struct sockaddr* )&seradd,sizeof(seradd));
    if (ret333<0){
        printf("connect error/n");
        return -1; 
    }   
    int n1 =0, n2=0;
    char buf[256];
    while (1 ){
        memset(buf,0x00,sizeof(buf));
        //从电脑键盘输入数据
        printf("客户端please type in a word,小写字母\n");
        n1 =read (STDIN_FILENO,buf,sizeof(buf));
        //发送数据给服务器
        write(sfd2,buf,n1);

        //读取服务器返回的数据
        memset(buf,0x00,sizeof(buf));
        n2 = read (sfd2,buf,sizeof(buf));
        printf("客户端,接受到的数据为%s\n", buf);
        if (n2<=0){
            printf("server已关闭,或者读到的字符为0/n");
            break;
        }
    }   
    close(sfd2);
return 0;
}
?2.2 将客户端IP 和端口都打印出来

?刚才accept函数第二三个参数都是iNULL? 现在再来看一下accept函数

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

? ? ? 从所有请求pending (悬而未决)的请求连接的队列中,找出第一个出来,获得一个新的文件描述符
? ? ? ?addr是传出参数,保留客户的地址,所以这是客户地址
? ? ? ?第三个参数,是传入传出参数,是地址长度,需要先制作出来,再&取地址

? ?//将网络大端模式的地址,转化为字符串
? ? const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

注意,这个“大端格式的地址”指的是32位IP ,而sockaddr_in结构体里面包含很多东西,ip地址只是结构体成员之一
不要混淆,inet_ntop第二个参数别写成&addr结构体 ??

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include<netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>
int main() {
    int sfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sfd <0){
        printf("socket fun error/n");
        return -1; 
    }   

    //定义一个地址结gou体
    struct sockaddr_in myad;
    //清空  memory
    bzero(&myad, sizeof(myad));
    myad.sin_family =AF_INET;
    myad.sin_port =htons(8888);
    myad.sin_addr.s_addr = htonl (INADDR_ANY);


    int ret = bind(sfd, (struct sockaddr *)&myad, sizeof(myad));

if (ret<0) {
        printf("bind error/n");
        return -1;
    }

    //将socket从主动变为被动(服务器必备),这样可以监听来自客户的请求
    listen(sfd,128);  
    

    //定义一个地址结gou体接受客户端地址结构体
    struct sockaddr_in dst;
    bzero(&myad, sizeof(myad));
    dst.sin_family =AF_INET;
    dst.sin_port =htons(8888);
    socklen_t dstleng = sizeof(dst);
    //为什么写这个,因为accept第三个参数也是指针,只能先制作出来
    int newfd = accept (sfd, (struct sockaddr* )&dst, &dstleng);
    if (newfd <0) {
        printf("服务端,accept error、\n");
        return -1;
    }
    char addstring[128];
    memset(addstring, 0x00,128);
     printf("服务器端,get connect,客户端地址是:\n");
    printf("IP:%s,PORT: %d\n", inet_ntop(AF_INET, &dst.sin_addr.s_addr,addstring,sizeof(addstring)), ntohs(dst.sin_port));


//把客户端发送过来的数据读出来
   int i =0;
   int n =0;
   char buf[1024];

    while (1 ){
        memset(buf,0x00,sizeof(buf));
        n = read (newfd,buf,sizeof(buf));
        if (n<=0){
            printf("客户端已关闭,或者读到的字符为0/n");
            break;
        }
        for (i=0;i<n;i++){
            buf[i] =toupper(buf[i]);
        }
        printf("服务器端。客户端的数据变成大写了\n");
    //把数据传回客户端,变成大写了已经
        write (newfd, buf, n);
    }
    close(newfd);      
close(sfd);     
return 0;  
 }

文章来源:https://blog.csdn.net/warmingsummer/article/details/135424746
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。