1.套接字的地址结构:

  

 typedef uint32_t in_addr_t;  //32位无符号整数,用于表示网络地址
struct in_addr{
in_addr_t s_addr;  //32位 ipv4 地址
}
typedef uint16_t in_port_t;  //16位无符号整数,用于表示端口号
struct sockaddr_in{
uint8_t sin_len;      //结构长度,8位无符号整数
sa_family_t sin_family;  //套接字地址族
in_port_t sin_port;    //16位 TCP 或 UDP 端口号
struct in_addr sin_addr;  //32位 ipv4 地址
char sin_zero[];    //暂时不用。总置为0
}

2.创建套接字函数 socket

int socket(int family , int type , int protocol)

  • family : 说明网络程序采用的通信协议族(比如 AF_INET 对应于 TCP/IP 协议族)
  • type : 网络程序所采用的通信协议(SOCKET_STREAM 表示创建 TCP 协议套接字,SOCK_DGRAM 表示创建 UDP 套接字,SOCK_RAW 表示创建原始套接字)
  • protocol : 由于指定了 type ,所以这里一般用 0 来代替就可以了
  • socket 函数成功时返回套接字描述符,失败时返回 -1

3.绑定函数 bind

int bind(int sockfd , struct sockaddr *my_addr , int addrlen)

  • sockfd : 由 socket调用 返回的套接字描述符
  • my_addr : 一个指向与协议对应的地址结构的指针。使用时需要讲指向特定协议地址结构的指针转换位指向 sockaddr 类型的指针。
  • addrlen  : sockaddr结构的长度
  • bind 函数成功时返回0,失败时返回-1

4.监听函数  listen

int listen(int sockfd,int backlog)

  • sockfd : 绑定后的套接字描述符
  • backlog : 设置请求排队的最大长度。当由多个客户端请求和服务器连接时,该参数表示可以接收的排队长度
  • listen函数调用成功返回0,失败返回-1

5.接受函数 accept

int accept(int sockfd , struct sockaddr *cliaddr , int *addrlen)

  • accept仅被 tcp 服务器调用。它从已完成连接的队列头返回下一个已完成的连接,若已完成连接的队列为空,则进入睡眠状态。
  • sockfd : 执行监听(listen)之后的套接字描述符。
  • client : 返回连接对方的套接字地址结构
  • addrlen : 返回对方套接字地址结构(client)的长度
  • accept 函数成功执行后会返回一个全新的描述符,代表与客户端的 tcp 连接。若失败则返回 -1

注意:监听套接字和已连接套接字是不同的两个概念。一个给定的服务器通常只会生成一个监听套接字并且一直存在,直到该服务器关闭。内核会为每个被接受的客户连接创建一个已连接套接字,当服务器完成某个客户的服务时,关闭该已连接套接字。监听描述符负责接收客户的连接请求,而已连接描述符负责与对应的客户进行数据传输。

6.连接函数 connect

int connect(int sockfd , struct sockaddr * serv_addr , int addrlen)

  • tcp 客户端通过 connect 函数来建立一个与 tcp 服务器的连接
  • sockfd : 套接字描述符
  • serv_addr : 指向服务器套接字地址结构的指针,套接字地址结构必须含有服务器的 ip 地址和端口号
  • addrlen : serv_addr的长度

7.连接中止函数close

int close(int sockfd)  关闭套接字

下面是完整的 服务端 代码:

   #include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h> int main()
{
/*定义套接字描述符,客户和服务器的套接字地址变量*/
int sockfd , new_fd; //定义监听套接字和已连接套接字
struct sockaddr_in server; //服务端地址和其他信息
struct sockaddr_in client; //客户端地址和其他信息
int sin_size , port = ; //定义端口号 /*服务器端开始建立 socket 描述符*/
if((sockfd = socket(AF_INET , SOCK_STREAM , ))==-)
{
printf("Socket error : %s\n",strerror(errno));
exit();
}
/*设置地址重用选项。由于系统默认只允许一个套接字绑在一个特定的协议地址上,并且当套接字关闭后系统仍不允许在该地址上绑定其他套接字。*/
int opt = SO_REUSEADDR;
setsockopt(sockfd , SOL_SOCKET , SO_REUSEADDR , &opt , sizeof(opt));
/*套接字绑定特定地址和端口,进入监听状态*/
bzero(&server , sizeof(struct sockaddr_in)); //将字节字符串前 n 个字节置0
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(port); //填充套接字地址结构,包括地址族,ip和端口号
/*sockfd 绑定到套接字地址*/
if(bind(sockfd , (struct sockaddr *)(&server) , sizeof(struct sockaddr))==-)
{
printf("Bind error : %s\n",strerror(errno));
exit();
}
/*sockfd 进入监听状态*/
if(listen(sockfd , )==-)
{
printf("Listen error : %s\n",strerror(errno));
exit();
}
sin_size = sizeof(struct sockaddr_in);
/*接收连接请求*/
if((new_fd = accept(sockfd , (struct sockaddr *)(&client) , &sin_size))==-)
{
printf("Accept error"%s\n",strerror(errno));
exit();
}
    printf("You got a connection from client's ip is %s , port is %d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); /*传输数据*/
if(write(new_fd , "hello" , strlen("hello"))==-)
{
printf("Write error : %s\n",strerror(errno));
exit();
}
/*关闭套接字*/
close(new_fd);
close(sockfd); return ;
}

客户端代码:

  

   #include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
int main()
{
int sockfd;
   char buffer[];
struct sockaddr_in server;
int port = ,nbytes; //参见服务端代码
char *serverip = "127.0.0.1"; //设置服务器地址为本机
/*创建套接字*/
if((sockfd = socket(AF_INET , SOCK_STREAM , ))==-)
{
printf("Socket error:%s\n",strerror(errno));
exit();
}
/*连接服务器*/
bzero(&server , sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
/*地址格式转换*/
if(inet_aton(serverip , &server_addr.sin_addr)==)//转换字节序同时给 sin_addr 赋值服务端 ip
{
printf("The server IP is not right !\n");
exit();
}
server.sin_port = htons(port);
//填充服务端的套接字结构 /*调用 connect 函数来连接到服务器*/
if((connect(sockfd , (struct sockaddr *)(&server) , sizeof(struct sockaddr)))==-)
{
printf("Connect error:%s\n",strerror(errno));
exit();
}
nbytes = read(sockfd , buffer , );
   if(nbytes < )
   {
     printf("Read error:%s\n",strerror(errno));
     exit();
   }
close(sockfd);
   printf("Received %d bytes :%s\n",nbytes , buffer);
return ;
}

stdio.h : 包含标准输入输出函数 printf()

stdlib.h : 包含异常退出函数 exit()

errno.h : 包含报告错误信息函数 strerror(errno)

string.h : 包含字符串处理函数

netinet/in.h : 包含多个与网络程序相关的函数和数据结构

arpa/inet.h : 包含 write和close 函数

unistd.h : inet_ntoa()函数

有关 tcp/ip 协议和 大字节序小字节序,大家可以自行百度,我在这里就不详细叙述了。

Linux系统C语言socket tcp套接字编程的更多相关文章

  1. UNP学习笔记1——基本TCP套接字编程

    1 套接字地址结构 大多数套接字函数都需要一个指向套接字地址结构的指针作为参数.每个协议族都定义了自己的套接字结构.这些套接字的结构以sockaddr_开头,以每个协议族唯一的后缀名结尾. 1.1 I ...

  2. TCP套接字编程模型及实例

    摘要:     本文讲述了TCP套接字编程模块,包括服务器端的创建套接字.绑定.监听.接受.读/写.终止连接,客户端的创建套接字.连接.读/写.终止连接.先给出实例,进而结合代码分析. PS:本文权当 ...

  3. 【UNIX网络编程(四)】TCP套接字编程具体分析

    引言: 套接字编程事实上跟进程间通信有一定的相似性,可能也正由于此.stevens这位大神才会将套接字编程与进程间的通信都归为"网络编程",并分别写成了两本书<UNP1> ...

  4. Linux Socket 原始套接字编程

    对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发 ...

  5. TCP套接字编程

    一.套接字(socket)函数 图1给出了在一个TCP客户与服务器通信的流程.服务器首先启动,稍后某个客户启动,它试图连接到服务器.假设客户给服务器发送一个请求,服务器处理该请求,并且给客户发回一个相 ...

  6. 【UNIX网络编程(二)】基本TCP套接字编程函数

    基于TCP客户/server程序的套接字函数图例如以下: 运行网络I/O.一个进程必须做的第一件事就是调用socket函数.指定期望的通信协议类型. #include <sys/socket.h ...

  7. 套接字编程相关函数(2:TCP套接字编程相关函数)

    本文摘录自<UNIX网络编程 卷1>. 基本套接字函数 socket函数 为了执行网络I/O,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型.其定义如下: #in ...

  8. <网络编程>基本TCP套接字编程

    tcp提供了可靠传输,当tcp向另一端发送数据的时候,要求对端返回一个确认.如果没有接收到确认,tcp就重传数据并且等待更长时间,数次重传失败后,tcp才放弃. 建立一个tcp连接会发生如下事情: 服 ...

  9. unix网络编程——TCP套接字编程

    TCP客户端和服务端所需的基本套接字.服务器先启动,之后的某个时刻客户端启动并试图连接到服务器.之后客户端向服务器发送请求,服务器处理请求,并给客户端一个响应.该过程一直持续下去,直到客户端关闭,给服 ...

随机推荐

  1. XCOM2中敌对生物设计分析(ADVENT篇)

    最近,在制作游戏Demo--DroneAssmble的过程中,对于敌对生物的设计,参考了幽浮系列的相关设定,因此着手对幽浮2中的主要敌人进行分析. 我们知道, XCOM2中的敌对生物主要由" ...

  2. [SDOI2010]所驼门王的宝藏

    题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为"先知"的Alpaca L. Sotomon是这个家族的领袖,外人也称其为"所驼门王". ...

  3. 用Html5/CSS3做Winform,一步一步教你搭建CefSharp开发环境(附JavaScript异步调用C#例子,及全部源代码)上

    本文为鸡毛巾原创,原文地址:http://www.cnblogs.com/jimaojin/p/7077131.html,转载请注明 CefSharp说白了就是Chromium浏览器的嵌入式核心,我们 ...

  4. Linux: Bash基本命令

    切换目录 cd 查看当前目录 pwd 生成目录 mkdir 搜索文件 查看当前的文件 ls 删除文件但保留特定类型 rm !(**) 例如: rm !(.tex|*.eps)其中,.tex, .eps ...

  5. Matlab: 路径的操作

    添加相对路径 在matlab中当代码很多时常常将结果存在不同的文件夹下面,常常使用相对路径对函数进行调用,但有时会存在问题.举个栗子: 代码结构如下: /codes/A/AA/code1.m /cod ...

  6. jq和js插件的各个文件夹里放置的内容

    1. demo文件夹,存放各种实例. 2. dist文件夹,全称是distribution.在某些框架中,因为开发和发布的内容或者代码形式是不一样的(比如利用Grunt压缩等等),这时候就需要一个存放 ...

  7. PGI Compiler for OpenACC Output Syntax Highlighting

    PGI Compiler for OpenACC Output Syntax Highlighting When use the PGI compiler to compile codes with ...

  8. JQuery实战——页面进度条效果

    今早逛阮一峰大神的博客 ECMAScript 6 入门 时候看到页面顶部有个进度条显示当前浏览的进度,如图: 顶部进度条会根据当前页面高度进行宽度调整,实战一番,视觉使用animated方法实现.下面 ...

  9. angularLoad(用以异步加载js文件)

    angularLoad(用以异步加载js文件) 使用方法: 1.执行命令 下载 lib npm install angular-load --save 2.index.html引用js <scr ...

  10. 本地服务器 windows server 2008 datacenter conn /as sysdba 提示 ora-01031 insufficient privileges

    原因是需要把当前用户administrator(为例)添加到ora_dba组里. 服务器管理器--配置--本地用户和组--组