关于socket编程单向发送消息

文章介绍了Socket编程的基础知识,展示了如何使用C语言创建一个简单的TCP连接,包括套接字的创建、连接到服务器以及发送数据。主要涉及的函数有socket(),connect(),inet_aton()等。
摘要由CSDN通过智能技术生成

Socket编程是一种用于在不同的计算机之间建立网络连接通信的编程技术。它是通过在不同的计算机之间建立一个“套接字”(socket),使得程序能够进行网络连接通信。Sockets可以在不同的互联网协议中进行,最常见的是TCP和UDP。通过Socket编程,程序可以在不同的计算机之间传输数据,从而实现各种网络应用程序,如电子邮件、网页浏览器、文件传输等。

 

本代码演示简单的单向发送数据;

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
 #include <stdlib.h>

#define MSG "hallo world"

int main(int argc,char** argv)//argc和argv的讲解在后面
{
        int                     sockfd=-1;//习惯把初始值设为负值,这样发生错误了能明显看出来
        int                     rv=-1;
        struct sockaddr_in      servaddr;
        char                    *servip;
        int                     port;
        char                    buf[1024];


        if(argc<3)
        {
                printf("Program usage:%s [servip] [port]\n",argv[0]);
                return -5;
        }

        servip=argv[1];
        port=atoi(argv[2]);//在命令行输入的为字符串,需要转换问int类型,相关函数百度
        printf("The IP is:%s   port is:%d\n",servip,port);
        sockfd =socket(AF_INET ,SOCK_STREAM,0);
        if(sockfd<0)//习惯每一次使用函数都判断返回值,返回值小于0的证明该函数出错,易修改
        {
                printf("socket is failure :%s\n",strerror(errno));

                return -1;
        }
        printf("The socket is seccessfully\n");
        memset(&servaddr,0,sizeof(servaddr));//习惯性用之前把数组里赋值为0,也可以叫清空数据
        servaddr.sin_family =AF_INET;
        servaddr.sin_port = htons(port);
        inet_aton(servip,&servaddr.sin_addr);


       
                rv=connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
                if(rv<0)
                {
                        printf("Connect to server[%s:%d] failure:%s\n",servip,port,strerror(errno));
                        return -2;

                }
                printf("connect to server [%s:%d] sucessfully\n",servip,port);
                memset(buf,0,sizeof(buf));
                rv=write(sockfd,MSG,strlen(MSG));
                if(rv<0)
                {
                        printf("Write to server by sockfd[%d]failure:%s\n",sockfd,strerror(errno));
                        return -3;
                }
                rv=read(sockfd,buf,sizeof(buf));
                if(rv<0)
                {
                        printf("Read data from server by sockfd[%d] failure:%s\n",sockfd,strerror(errno));
                        return -4;
                }
                else if(rv==0)
                {
                        printf("Socket[%d] get disconnected\n",sockfd);
                        return -5;

                }
                else if(rv>0)
                {
                printf("Read %d bytes data from sever:%s",rv,buf);

                }

        
        close(sockfd);//结束后记得一定要关闭文件

return 0;
}

关于在main括号里的参数,第一个argc是命令行参数的个数,第二个参数是一个字符串的数组,你也可以写成char *argv[],每一个元素表示一个指针,指向每一个 参数,其实还有第三个参数,在此不讲,例如该程序,如果编译之后只是使用./a.out话会出现以下错误,所以要使用./编译后的名字 IP地址 端口号后才能正常运行,该方法避免了更改IP和端口号需要重新编译的麻烦,但是该程序还不够完善,只能发送一次,下一篇文章会出完整代码。

 socket的头文件和原型为

 第一个参数为

 

第二个参数为

domain
参数表示套接字要使用的协议簇,协议簇的在“linux/socket.h”里有详细定义,常用的协议簇:
AF_UNIX(本机通信)
AF_INET(TCP/IP – IPv4)
AF_INET6(TCP/IP – IPv6)

type
“type”参数指的是套接字类型,常用的类型有:
SOCK_STREAM(TCP流)
SOCK_DGRAM(UDP数据报)
SOCK_RAW(原始套接字)

protocol
协议“protocol”一般设置为“0”,就是说在已经确定套接字使用的协议簇和类型时,这个参数的值就为0。
但是有时候创建初始套接字时,在domain参数未知情况下,即不清楚协议簇和类型时,protocol参数可以用来确定协议的种类。

sockaddr_in结构体包含以下字段:

  • sin_family:地址族,通常设置为AF_INET表示IPv4协议。

  • sin_port:端口号,以网络字节序表示。

  • sin_addr:IP地址,以网络字节序表示。

  • sin_zero:填充字段,通常设置为0。

inet_aton函数是一个用来将IP地址转换为网络字节序的函数,
它能够识别有点分开的IP地址和它们的各个子网掩码,而且还能够
完成网络字节序的转换。它的定义形式如下:
 int inet_aton(const char *cp, struct in_addr *inp); 
函数 inet_aton()用来将一个点分十进制的IP地址(例如192.168.1.1)转换成一个用网络字节顺序存储的 in_addr构体。该函数可以将给定的 IP址转换成一个长整数型数,这样在网络通信中使用起来更加方便快捷。该函数的第一个参数是一个以 NULL束的字符串,指向一个非空的 IP址(例如192.168.1.1),第二个参数 inp向一个 in_addr构体,函数将会把点分十进制的 IP址转换为网络字节顺序存储在in_addr构体中。 inet_aton数的返回值是一个整数,若转换成功就会返回非零的
值,若失败就会返回 0(零)。

connect函数

 值得注意的是第二个参数的类型于我们写的不一样,它是一个兼容的参数,为了方便两个结构体的使用

sockfd: 指定数据发送的套接字,解决从哪里发送的问题。内核需要维护大量IO通道,所以用户必需通过这个参数告诉内核从哪个IO通道,此处就是从哪个socket接口中发送数据。sockfd是先前socket返回的值。

server_addr: 指定数据发送的目的地,也就是服务器端的地址。这里服务器是针对connect说的,因为connect是主动连接的一方调用的,所以相应的要存在一个被连接的一方,被动连接的一方需要调用listen以接受connect的连接请求,如此被动连接的一方就是服务器了。

addrlen: 指定server_addr结构体的长度。我们知道系统中存在大量的地址结构,但socket接口只是通过一个统一的结构来指定参数类型,所以需要指定一个长度,以使内核在进行参数复制的时候有个有个界限。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值