一.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程序编写

/**********************************************************************************      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 <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#define PORT 8899
#define BACKLOG 13int 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;
}

服务器端client.c程序编写

/**********************************************************************************      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 <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#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;
}



客户端连接服务器之后进行读写操作

网络socket编程(c语言)相关推荐

  1. java基础 day12-FileInputStream类,文件的复制,缓冲流,Propertes文件,xml文件读写,网络socket编程(构建TCP客户端),内部类

    FileInputStream类的其他常用方法() /**在project下新建temp文件,内容为abcdef*FileInputStream类的其他常用方法:* int available():返 ...

  2. 网络socket编程指南 (转)

    Beej网络socket编程指南 -------------------------------------------------------------------------------- 介绍 ...

  3. java web接收tcp_Java多线程实现TCP网络Socket编程(C/S通信)

    开篇必知必会 在前一篇<基于TCP协议网络socket编程(java实现C/S通信)>,实际存在一个问题,如果服务器端在建立连接后发送多条信息给客户端,客户端是无法全部接收的,原因在于客户 ...

  4. 网络socket编程--多路复用

    一.五种网络I/O模型 1.什么是I/O I/O在计算机中指Input/Output,也就是输入和输出.由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常 ...

  5. 网络Socket编程

    Microsoft.Net Framework为应用程序访问Internet提供了分层的.可扩展的以及受管辖的网络服务,其名字空间System.Net和System.Net.Sockets包含丰富的类 ...

  6. Java 网络 socket 编程

    使用套接字实现基于 TCP 协议的服务器和客户机程序 依据 TCP 协议,在 C/S 架构的通讯过程中,客户端和服务器的 Socket 动作如下: 客户端: 1.用服务器的 IP 地址和端口号实例化 ...

  7. Linux下网络socket编程——实现服务器(select)与多个客户端通信

    一.关于socket通信 服务器端工作流程: 调用 socket() 函数创建套接字 用 bind() 函数将创建的套接字与服务端IP地址绑定 调用listen()函数监听socket() 函数创建的 ...

  8. 建立网络链接编程C语言,用C语言编写一个网络蜘蛛来搜索网上出现的电子邮件地址...

    可能大家经常要去互联网上搜索特定的内容,比如收集大量邮件地址,如果用google之类的搜索引擎是没法实现这种特定功能的,所以用C语言来写一个吧.它的功能就是不断去取得网络上的页面,然后分析出网页上出现 ...

  9. 【java】网络socket编程简单示例

    1 package 网络编程; 2 3 import java.io.IOException; 4 import java.io.PrintStream; 5 import java.net.Serv ...

  10. java 网络io详解_Java网络socket编程详解

    或许有点长 但是一步步教你 我想你也愿意看7.2面向套接字编程 我们已经通过了解Socket的接口,知其所以然,下面我们就将通过具体的案例,来熟悉Socket的具体工作方式7.2.1使用套接字实现基于 ...

最新文章

  1. 自定义堆栈(回文检测)
  2. 【干货】Dask快速搭建分布式集群(大数据0基础可以理解,并使用!)
  3. js/jquery判断浏览器 停止加载
  4. Json序列化提示缺少编译器要求的成员“ystem.Runtime.CompilerServices.ExtensionAttribute..ctor”...
  5. 快速了解Druid -- 实时大数据分析软件
  6. VBS使文本框的光标位于所有字符后
  7. 请重视!服务器这几个“异常”可能性预警
  8. ML《决策树(三)CART》
  9. 韩国巨型机器人曝光,走一步地动山摇
  10. 遇到一个php的错误,php初学者常见的几个错误及解决方法
  11. c++string类的相关操作
  12. 表情库 android,Emojicon
  13. linux 网络对时
  14. 张子阳:如何在30岁前年薪超过30万
  15. 计算机软件专业硕士论文,软件工程硕士论文范文
  16. js中apply、bind、call的用法和区别
  17. 前端的一些实用算法题
  18. 自定义配置文件 /etc/httpd/conf.d
  19. 警猫眼App:闲置安卓旧手机DIY变成安防监控云端摄像头
  20. Loki 学习总结(1)—— Loki 中小项目日志系统的不二之选

热门文章

  1. 用Python写前端
  2. java8实战教程,[JAVA] 汪大神Java8新特性及实战视频教程完整版
  3. 关于DNF的多媒体包NPK文件的那些事儿(10) - SPK文件
  4. eharts 中国地图添加城市(散点图实现,含获取城市坐标、图片转base64、自定义散点样式)
  5. 服务器缺少dll文件,遇到DLL文件缺失或者损坏怎么办 DLL文件修复教程
  6. 著作权登记信息采集表
  7. 小说站源码php采集,关于PHP批量采集----采集小说站有感
  8. 加载gif图片html,JS实现的自定义显示加载等待图片插件(loading.gif)
  9. java snap7_Snap7 referance manual PDF 下载
  10. colorui开发文档_小程序原生高颜值组件库--ColorUI