网络socket编程(c语言)[亲测有效] -金沙1005

网络socket编程(c语言)[亲测有效]一.socket通信简介socket是对tcp/ip协议的封装,socket本身并不是协议,而是一个调用接口(api),通过socket,我们才能使用tcp/ip协议,主要利用三元组【ip地址,协议,端口】。socket起源于unix,而unix/linux基本哲学之一就是“一切皆文件”,都可以用“打开open–>读写write/read–>关闭close”模式来操作。socket()函数返回一个整型的socket描述符,随后的连接建立、数据传输等操作都是通过该socket实现的。

一.socket通信简介

socket是对tcp/ip协议的封装,socket本身并不是协议,而是一个调用接口(api),通过socket,我们才能使用tcp/ip协议,主要利用三元组【ip地址,协议,端口】。
socket起源于unix,而unix/linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。
socket()函数返回一个整型的socket描述符,随后的连接建立、数据传输等操作都是通过该socket实现的。socket是应用层与tcp/ip协议族通信的中间软件抽象层。
在这里插入图片描述
二.网络socket客户端和服务器端连接过程如下:
在这里插入图片描述

1.1 socket()
int socket(int domain,int type, int protocol);
返回值: 成功:返回指向新创建的socket的文件描述符,失败:返回-1。

domain:即协议域,又称为协议族(family)。常用的协议族有,af_inet、af_inet6、af_local(或称af_unix,unix域socket)、af_route等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如af_inet决定了要用ipv4地址(32位的)与端口号(16位的)的组合、af_unix决定了要用一个绝对路径名作为地址。
type:创建的套接字的类型,常用sock_stream(流式套接字),sock_dgram(数据报套接字)

protocol: 传0 表示使用默认协议。

1.2 bind()
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
返回值:函数执行成功返回0,否则返回-1, 并设置错误代码。

sockfd:需要绑定的套接字文件描述符。
addr:存入网络类型,网络地址和端口号的结构体。
addrlen:addr结构体的长度。

ipv4使用的结构体是struct sockaddr_in类型,所以绑定时需要强制类型转换成struct sockaddr类型
struct sockaddr_in
{
sa_family_t sin_family; /* 2 bytes address family, af_xxx such as af_inet /
in_port_t sin_port; /
2 bytes port*/
struct in_addr sin_addr; /* 4 bytes ipv4 address*/
unsigned char sin_zero[8]; /* 8 bytes unused padding data, always set be zero */
};

struct sockaddr
{
sa_family_t sa_family; /* 2 bytes address family, af_xxx /
char sa_data[14]; /
14 bytes of protocol address */
}

在使用bind时常用的两个函数:htonshtonl,在将一个地址绑定到socket的时候,先将主机字节序转换成为网络字节序
serv_addr.sin_port = htons(listen_port);
serv_addr.sin_addr.s_addr = htonl(inaddr_any);

ip地址“127.0.0.1”这是点分十进制形式的字符串形式,而在结构体struct sockaddr_in 中ip地址是以32位(即4字节整形类型)数据保存的,这时我们可以调用 inet_aton() 函数将点分十进制字符串转换成 32位整形类型

1.3 listen()
int listen(int sockfd,int backlog);
返回值:成功返回0,失败返回-1。
sockfd: socket文件描述符
backlog: 排队建立3次握手队列和刚刚建立3次握手队列的链接数和

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

属性相同的连接套接字,并为这个套接字分配一个文件描述符,然后以这个描述符返回
返回值:若成功则返回一个非负整数标识这个连接套接字,发生错误时返回-1。
sockfd:一个正在用于监听功能下的套接字的文件描述符。
addr:用于储存接受到的客户端的网络信息的结构体(参考bind下的使用)
addrlen:addr结构体长度

1.5 connect()
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

sockfd: 客户端的socket()创建的描述字
addr: 要连接的服务器的socket地址信息,这里面包含有服务器的ip地址和端口等信息
addrlen: socket地址的长度

客户端server.c程序编写

/********************************************************************************* * js555888金沙老品牌 copyright: (c) 2021 jiaoer237 * all rights reserved. * * filename: socket_server.c * description: this file * * version: 1.0.0(11/21/2021) * author: yanp <2405204881@qq.com> * changelog: 1, release initial version on "11/21/2021 01:59:13 pm" * ********************************************************************************/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define port 8899
#define backlog 13
int socket_server_init(char *listen_ip,int listen_port);
int main()
{ 

int listen_fd,clien_fd=-1;
struct sockaddr_in cli_addr;
socklen_t cliaddr_len;
char buf[1024];
int rv=-1;
listen_fd=socket_server_init(null,port);/*初始化socket函数*/
while(1)
{ 

printf("\nstart waiting and accept new client connect...\n");
clien_fd=accept(listen_fd,(struct sockaddr*)&cli_addr,&cliaddr_len);/*accept调用*/
if(clien_fd<0)
{ 

printf("accept new client failure:%s\n",strerror(errno));
return -1;
}
printf("accept new client[%s:%d] with fd [%d]\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),clien_fd);
memset(buf,0,sizeof(buf));
rv=read(clien_fd,buf,sizeof(buf));
if(rv<0)
{ 

printf("read data from socket[%d] failure:%s\n",clien_fd,strerror(errno));
close(clien_fd);
continue;
}
else if(0==rv)
{ 

printf("read data from socket[%d] failure:%s\n",clien_fd,strerror(errno));
close(clien_fd);
continue;
}
printf("read %d data from server client [%d] and echo it back:'%s'\n",rv,clien_fd,buf);
if(write(clien_fd,buf,rv)<0)
{ 

printf("write %d bytes data back to client[%d] failure:%s\n",rv,clien_fd,strerror(errno));
close(clien_fd);
}
}
return 0;
}
int socket_server_init(char *listen_ip,int listen_port)
{ 

int listenfd;
struct sockaddr_in servaddr;
if((listenfd=socket(af_inet,sock_stream,0))<0)/*创建socket描述符*/
{ 

printf("socket_server to create a tcp socket fd failure:[%s]\n",strerror(errno));
return -1;
}
printf("create a tcp socket fd[%d] success\n",listenfd);
int on=1;  
if((setsockopt(listenfd,sol_socket,so_reuseaddr,&on,sizeof(on)))<0) /*让端口号能够立即重复使用*/
{ 

printf("setsockopt failure:%s",strerror(errno));
return -2;
}
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=af_inet;
servaddr.sin_port=htons(port);
if(!listen_ip)/*加入传入ip地址则监听指定ip,否则监听所有ip*/
{ 

servaddr.sin_addr.s_addr=htonl(inaddr_any);
}
else
{ 

servaddr.sin_addr.s_addr=htonl(listen_port);
}
if(bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr))<0)/*绑定端口号和ip*/
{ 

printf("socket[%d] bind on port[%d] for ip address failure:%s\n",listenfd,listen_port,strerror(errno));
return -2;
}
printf("socket[%d] bind on port[%d] for ip address success\n",listenfd,listen_port);
listen(listenfd,backlog);
return listenfd;
}
网络socket编程(c语言)[亲测有效]

为防止网络爬虫,请关注公众号回复”口令”

激活idea 激活clion
datagrip dataspell
dotcover dotmemory
dottrace goland
phpstorm pycharm
resharper reshac
rider rubymine
webstorm 全家桶

服务器端client.c程序编写

/********************************************************************************* * js555888金沙老品牌 copyright: (c) 2021 jiaoer237 * all rights reserved. * * filename: socket_client.c * description: this file * * version: 1.0.0(11/21/2021) * author: yanp <2405204881@qq.com> * changelog: 1, release initial version on "11/21/2021 08:49:25 pm" * ********************************************************************************/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define server_port 8899
#define msg_str "hello yanp, unix network program world!"
#define server_ip "192.168.1.120"
int main(int argc,char **argv)
{ 

int conn_fd = -1;
int rv = -1;
char buf[1024];
struct sockaddr_in serv_addr;
conn_fd=socket(af_inet,sock_stream,0);/*socket创建客户端的描述符*/
if(conn_fd<0)
{ 

printf("create client socket failure:%s\n",strerror(errno));
return -1;
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = af_inet;
serv_addr.sin_port = htons(server_port);
inet_aton(server_ip,&serv_addr.sin_addr);/*将点分十进制转换成32位整型类型*/
if(connect(conn_fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0)/*连接服务器*/
{ 

printf("client[%d] connect to server[%s:%d] failure:%s\n",conn_fd,server_ip,server_port,strerror(errno));
return -1;
}
if(write(conn_fd,msg_str,strlen(msg_str))<0)
{ 

printf("write data to server[%s,%d] failure:%s\n",server_ip,server_port,strerror(errno));
return -2;
}
memset(buf,0,sizeof(buf));
rv=read(conn_fd,buf,sizeof(buf));
if(rv<0)
{ 

printf("read data from server failure:%s\n",strerror(errno));
return -3;
}
else if(rv==0)
{ 

printf("client connetc to server get disconnect\n");
return -4;
}
printf("read %d bytes from server:'%s'\n",rv,buf);
return 0;
}

在这里插入图片描述
在这里插入图片描述
客户端连接服务器之后进行读写操作

js555888金沙老品牌的版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由思创斯整理,转载请注明出处:https://ispacesoft.com/162947.html

(0)

相关推荐

  • jsp服务器搭建_服务器怎么做镜像ghost很多人都不知道国内有jhost免费的jsp服务器,有些人知道,却不知道怎么用,下面我就简述下,送给爱学习,喜爱java开发的朋友首先,无论你使用的是eclipse还是myeclipse开发的项目,导出项目成war包,然后登陆你的jhost,打开“我的空间”、“网站空间”,上传刚刚导出的war包到“网站空间”内,然后解压此war包,即可,其实很简单jhost邀请码地址:

  • 根据用户输入的运算量和操作符,使用switch语句_c语言用户标识符的命名规则要求:编写程序,实现用户在输入星期几(1~7的整数)后,可以显示当天的食谱内容。 假设一周食谱如一: 星期一:青菜 星期二:鸡肉 星期三:鱼肉 星期四:猪肉 星期五:鸡蛋 星期六:豆制品 星期日:海鲜

  • python appium自动化测试-使用android模拟器(详细)做app的ui自动化测试时,我们往往会使用真机跑自动化测试脚本,因为这样才是最真实的使用场景。但前期调试脚本的话,可以先使用模拟器,这样相对更加方便。不推荐使用androidsdk里自带模拟器,太卡。这里介绍两款我正在用于做自动化测试的模拟器:genymotion与夜神模拟器。一,genymotion1,注册账号使用genymotion时需要登录账号,我们需要去genymotion金沙1005官网注册账号。金沙1005官网地址:https://www.genymotion.com/金沙1005官网金沙1005首页点击【signin】

  • sobel算子及c 实现[亲测有效]sobel算子是一个离散的一阶微分算子,用来计算图像灰度函数的近似梯度。在空间域上sobel算子很容易实现,执行速度快,对部分噪声具有平滑作用,还能够提供较为精确的边缘方向信息,缺点是边缘定位精度不够高。边缘是指一个物体与另一个物体的分界处,一般边缘内外处都会有灰度值上的差异,sobel算子就是通过像素点空间邻域内上下,左右相邻点的灰度加权运算,求取物体边缘。经典sobel的卷积

  • stm32 spi驱动oled12864原理图和源代码分享一、原理图芯片引脚连接二、驱动程序spi.c#include”spi.h”voidspi1_init(void){ gpio_inittypedefgpio_initstructure;spi_inittypedefspi_initstructure; rcc_apb2periphclockcmd( rcc_apb2periph_gpioa,enable);//porta时钟使能 rcc_apb2periphclockcmd( rcc_apb2perip

    2022年10月24日
  • 不要在广播的onreceive()方法中执行耗时操作不要在onreceive()方法中添加过多的逻辑或执行耗时操作,因为onreceive()方法运行在主线程中,耗时操作会导致anr。同时,广播接收器中不允许开启子线程:对于静态注册的广播接收器来说,广播接收器对象的生命周期较短,执行完onreceive()方法就会变为垃圾对象而被回收,在子线程执行完之前,若对应的activity退出,他们所在进程就变成了空进程(没有任何活动组件的进程),系…

  • 远程控制软件和木马的区别——病毒木马 001「建议收藏」1.首先,无论是用木马还是用正规的远程控制软件,要实现远程操控对方电脑,都需要在被控的电脑上安装一个被控端,如果不安装那么不可能实现控制。灰鸽子、黑洞等木马软件,会将被控端设计成全自动后台运行,点击一下后,被控端可能就消失掉了,其实它已经在后台悄悄的安装了。正规的远程控制软件,比如网络人、pcanywhere等被控端的安装符合常规软件的安装流程,有安装界面供客户选择和退出。被控端如果隐藏安装,那么杀毒软件会认为你是木马,如果有安装界面正常安装,并且可以退出、卸载,那么可以认为是正规的远程控制软件。2..

  • vue中引入echarts封装组件的两种方式(全局引入和按需引入)1. 安装echarts 2. 全局引入 3. 按需引入 4. 参考文档 1. 安装echarts 当然,你不使用vue-echarts也可以实现按需引入,就可以不安装vue-echarts,下面会讲到。 2. 全局引入 使用 import echarts from ‘echa…

发表回复

您的电子邮箱地址不会被公开。

联系金沙1005

关注“java架构师必看”公众号

回复4,添加站长微信。

附言:ispacesoft.com网而来。

关注微信
网站地图