https://www.cnblogs.com/ashen/p/4474360.html

#include <sys/socket.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdio.h>
5 #include <linux/in.h>
6 #include <sys/types.h>
7
8 #define PORT 7891
9
10 int main()
11 {
12 int socketfd,accsocfd;
13 struct sockaddr_in s_addr,r_addr;
14 socklen_t len;
15 int recdata;
16 char buf[1024];
17 memset(buf,0x00,sizeof(buf));
18 //创建套接字
19 if(-1 == (socketfd = socket(AF_INET,SOCK_STREAM,0))){
20 printf("socketfd is created failed!\n");
21 return -1;
22 } ;
23 printf("socket create success!\n");
24
25 //将本地协议地址与sockfd绑定
26 memset(&s_addr,0x00,sizeof(s_addr));
27 s_addr.sin_family = PF_INET;
28 s_addr.sin_port = htons(PORT);
29 s_addr.sin_addr.s_addr = htons(INADDR_ANY);//inet_addr_any 一个服务器可能有多个网卡,随便从中选1个
30 if(-1 == bind(socketfd,(struct sockaddr*)&s_addr,sizeof(s_addr))){
31 printf("bind failed!\n");
32 return -1;
33 }
34 printf("bind suc!\n");
35
36 //监听本地端口
37 if(-1 == listen(socketfd,10)){
38 printf("listen failed!\n");
39 return -1;
40 }
41 printf("listen suc!\n");
42
43 while(1){
44 len = sizeof(struct sockaddr);
45 accsocfd = accept(socketfd,(struct sockaddr *)&r_addr,&len);
46 if(-1 == accsocfd){
47 printf("accept failed!\n");
48 return -1;
49 }
50 printf("accept suc !\nServer get connect from %x port is %x",ntohl(r_addr.sin_addr.s_addr),ntohl(r_addr.sin_port));
51
52
53 //向客服端发送数据
54 if(-1 == write(accsocfd,"this is first data from sr!\n",50)){
55 printf("write failed!\n");
56 return -1;
57 }
58 printf("write suc!\n");
59
60
61 printf("*********************\n");
62
63 char recvBuf[100];
64
65 if(-1 ==recv(accsocfd, recvBuf, 100, 0)){
66 printf("recv failed!\n");
67 return -1;
68 }
69 printf("recv suc!\n");
70 printf("recvBuf = [%s]\n",recvBuf);
71 printf("recvBuf len is = [%d]\n",strlen(recvBuf));
72
73 close(accsocfd);
74
75 }
76 close(socketfd);
77 return 0;
78 }

//c.c

#include<sys/socket.h>
#include<string.h>
#include<linux/in.h>
#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
/*流程: TCP:(面向连接、可靠) 服务器端 WSAStartup->socket->bind->listen->accept->recv/send->closesocket->WSACleanup
客户端:WSAStartup->socket->connect->recv/send->closesocket->WSACleanup
*/
#define PORT 7891
int main()
{
int csocfd;
int recdata;
char buf[1024];
memset(buf,0x00,sizeof(buf));
struct sockaddr_in mysockaddr;
//创建套接字
if(-1 == (csocfd = socket(PF_INET,SOCK_STREAM,0))){
printf("csocfd failed!\n");
return -1;
}
printf("csocfd suc!\n"); //设置服务器的地址 memset(&mysockaddr,0x00,sizeof(mysockaddr));
mysockaddr.sin_family = PF_INET;
mysockaddr.sin_port = htons(PORT);
inet_pton(AF_INET,"172.19.230.113",&mysockaddr.sin_addr.s_addr);
//s_add.sin_addr.s_addr= inet_addr("172.19.230.113"); /* ip转换为4字节整形,使用时需要根据服务端ip进行更改 */ //connect to the sr
if(-1 == connect(csocfd,(struct sockaddr*)&mysockaddr,sizeof(mysockaddr))){
printf("connect failed!\n");
return -1;
}
printf("connect suc!\n"); if(-1 == (recdata = read(csocfd,buf,sizeof(buf)))){
printf("read failed!\n");
return -1;
}
printf("read suc!\n");
buf[recdata ] = '\0';
printf("recdata = [%s]\n",buf);
printf("recdata len is = [%d]\n",recdata); //memcpy(sendbuf,"this is data from cl!\n",);
if(-1 == send(csocfd, "this is data from cl!", 100, 0)){
printf("send faile\n");
return -1;
}
printf("send suc!\n"); close(csocfd); }

学习笔记也附上吧

0.socket编程的目的是为了解决网络上不同主机上的进程之间通信问题
网络中的数据传输实际上是一种I/O操作
socket描述符可以同文件操作符进行比较,可以用read、write、close等操作,socket代表通信管道的一个端点

1.C/S模式(以面向连接为例子) 
服务器工作过程:
打开一个通信通道,并告诉本地主机,服务器开了一特定端口接受客服请求。
等待客户请求。
接收到客户请求之后发送应答信号,创建一个新线程处理请求。
服务完成之后关闭通信通道和线程
继续等待客户请求。
客服端的工作过程:
打开一通信通道,连接到服务器的制定端口。
向服务器发送请求,并等待接受应答。
根据需要继续发送请求
请求结束后关闭通信信道
2. Socket 类型常用的有2种:流式:SOCK_STREAM 数据报:SOCK_DGRAM
主机字节序数据转换成网络字节序数据
uint32_t htonl(uint32_t hostint32);
uint16_t htons(uint16_t hostint16);
网络字节序数据转换成主机字节序数据
uint32_t ntohl(uint32_t netint32);
uint16_t ntohs(uint16_t netint16);

3.创建套接字
int socket(int family, int type,intprotocol);
功能:创建一个用于网络通信的I/O描述符(套接字)
参数:family:协议族 AF_INET,AF_INET6,AF_LOCAL,AF_ROUTE,AF_KEY
type: 套接字类型 套接字类型
protocol 协议类别 0,IPPROTO_TCP,IPPROTO_UDP,IPPROTO_SCTP
返回值:套接字
特点:(1)使用socket创建套接字时,系统不会分配端口 (2)使用socket创建的是主动套接字,但作为服务器,
需要被动等待别人的连接
头文件:#include<sys/socket.h>
示例:
int sockfd = 0;
sockfd = socket(AF_INET,SOCK_STREAM,0);
if( sockfd< 0){"failed !";exit(-1);}
4.服务器
4.1 绑定
int bind(int sockfd,const struct socketaddr *myaddr,socklen_t addlen);
功能:将本地协议地址与sockfd绑定
参数:sockfd ... myaddr:指向特定于协议的地址结构指针 addrlen:该地址结构的长度
头文件:<sys/socket.h>
备注: 二者的占用的内存大小是一致的,因此可以互相转化,从这个意义上说,他们并无区别。
sockaddr常用于bind、connect、recvfrom、sendto等函数的参数,指明地址信息。是一种通用的套接字地址。而sockaddr_in 是internet环境下套接字的地址形式。

//usr/include/bits/socket.h 
struct sockaddr{
sa_family_t sa_family; //2字节 /* 协议族 */
char sa_data[14]; //14字节 地址+端口号*/
};
// sockaddr_in是在头文件 /usr/include/netinet/in.h 中定义的
typedef uint32_t in_addr_t;
struct in_addr{
in_addr_t s_addr; //4字节
};
struct sockaddr_in{
sa_family_t sin_family; //2字节 /* 协议族 */
in_port_t sin_port; //2字节 /* Port number. 端口号 */
structin_addr sin_addr; //4字节/* Internet address. IP地址 */
unsigned char sin_zero[8]; //8字节 /* Pad to size of `struct sockaddr'. 用于填充的0字节 */
};
示例:
int sockfd;
struct sockadd_in mysock;
sockfd = socket(AF_INET,SOCKET_STREAM,0);

bzero(&mysock,sizeof(mysock));
mysock.sin_family = AF_INET;
mysock.sin_port = htons(800);
mysock.sin_addr.saddr = inet_addr("192.168.2.45") ; 
bind(sockfd,(struct sockaddr *)&mysock,sizeof(struct sockaddr));

//htons()作用是将端口号由主机字节序转换为网络字节序的整数值。(host to net)
//inet_addr()作用是将一个IP字符串转化为一个网络字节序的整数值,用于sockaddr_in.sin_addr.s_addr。
//inet_ntoa()作用是将一个sin_addr结构体输出成IP字符串(network to ascii)
4.2 监听
int listen(int sockfd, int backlog);
功能:将套接字由主动修改为被动 使操作系统为该套接字设置一个连接队列,用来记录所有连接到该套接字的连接
参数: sockfd:socket监听套接字 sockfd:socket监听套接字
返回值: 0 成功
头文件: <sys/socket.h>
示例:
int err_log;
err_log = listen(sockfd,10); 
4.3 从连接队列中取出一个已经建立的连接
int accept(int sockfd,struct sockaddr*cliaddr, socklen_t*addrlen);
功能:从已连接队列中取出一个已经建立的连接,如果没有任何连接可用,则进入睡眠等待
参数:sockfd:socket监听套接字
cliaddr:存放客服端套接字的地址结构,传出参数
addrlen:套接字地址结构长度
返回值:已连接的套接字(一个新的套接字,原先的套接字仍在监听)
头文件: <sys/socket.h>
示例:
struct sockaddr_in c_addr; 
struct sockadd_in mysock;
int sockfd;
char buf[BUFLEN]; 
int newfd; 
/*建立socket*/ 
sockfd = socket(AF_INET, SOCK_STREAM, 0);

bzero(&mysock,sizeof(mysock));
mysock.sin_family = AF_INET;
mysock.sin_port = htons(800);
mysock.sin_addr.saddr = inet_addr("192.168.2.45") ; 
/*把地址和本地端口帮定到套接字上*/ 
bind(sockfd,(struct sockaddr *)&mysock,sizeof(struct sockaddr));
/*侦听本地端口*/ 
listen(sockfd,11) ;
while(1){ 
newfd = accept(sockfd,(struct sockaddr*) &c_addr, &sizeof(c_addr));//生成一个新的套接字
printf("当前处理的是%s: %d\n",inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port));

备注:accept()函数 准备好了,系统调用accept()会有点古怪的地方的!你可以想象发生 这样的事情:有人从很远的地方通过一个你在侦听 (listen()) 的端口连接 (connect()) 到你的机器。它的连接将加入到等待接受 (accept()) 的队列 中。你调用 accept() 告诉它你有空闲的连接。它将返回一个新的套接字文 件描述符!这样你就有两个套接字了,原来的一个还在侦听你的那个端口, 新的在准备发送 (send()) 和接收 ( recv()) 数据。这就是这个过程! 
5.客服端(需要知道服务器的ip及端口号)
5.1 int connect(int sockfd,const struct sockaddr *addr,socklen_t len);
功能:主动跟服务器建立链接,建立链接之后传送数据(tcp协议)
部分参数说明:addr 需要链接的服务器地址结构
返回值:0 成功
头文件:#include <sys/socket.h>
示例:int sockfd;
int resCon;
//创建套结字
sockfd = socket(AF_INET,SOCKET_STREAM,0);
if(sockfd <0){ ... }
struct sockadd_in mysock;
memset(&mysock,0x00,sizeof(mysock));
mysock.sin_family = AF_INET;
mysock.sin_port = htons(8999);

mysock.sin_addr.saddr = inet_addr("192.168.2.45");
//这里也可以用inet_pton来转换 inet_pton(AF_INET,"192.168.2.45",&mysock.sin_addr.saddr);
//inet_pton:inet_pton 是inet_addr的扩展,将“点分十进制” -> “二进制整数”,int inet_pton(int af, const char *src, void *dst);反转inet_ntop

//主动连接服务器
resCon = connect(sockfd,(struct sockadd *)&mysock,sizeof(mysock));
if(resCon){...}

6.数据传送
6.1 通信
#define MAXLEN 512
while(1){
char send_buf[512];
char recv_buf[512];
memset(send_buf,0x00,sizeof(send_buf));
memset(recv_buf,0x00,sizeof(recv_buf));

//从流中读取MAXLEN-1个数据存入send_buf中
fgets(send_buf,MAXLEN,stdin);

write(sockfd,send_buf,strlen(send_buf));
read(sockfd,recv_buf,MAXLEN);
/*
recv和send 
  recv和send函数提供了和read和write差不多的功能.但是他们提供了第四个参数来控制读写操作。
int recv(int sockfd,void *buf,int len,int flags) 
int send(int sockfd,void *buf,int len,int flags) 
前面的三个参数和read,write相同,第四个参数能够是0或是以下的组合

*/

printf("recv_buf = [%s]",recv_buf);

}

close(sockfd);
6.2 发送数据与接受数据
ssize_t send(int sockfd, const void* buf,size_t nbytes, int flags);
功能:用于发送数据,不可以用tcp发送0长度的数据
部分参数说明;buf 待发送的数据缓存,nbytes发送的长度,flags套接字的标志,通常为0
返回值:成功发送的字节数

ssize_t recv(int sockfd, void *buf,size_t nbytes, int flags);
功能:接受网络数据
部分参数说明:buf 指向接受网络数据的缓冲区,nbytes 缓冲区的大小
7.关闭连接
关闭一个代表已连接套接字将导致另一端接收到一个0长度的数据包。
做服务器时:(1)关闭socket创建的监听套接字将导致服务器无法继续接受新的连接,但不会影响已经建立的连接
(2)关闭accept返回的已连接套接字将导致它所代表的连接被关闭,但不会影响服务器的监听

很多时候我都在期待3年后的自己是一个什么样的,5年后自己又是一个什么样的。因为未知,所以生命才更加精彩。

c--socket通信TCP篇的更多相关文章

  1. php socket通信(tcp/udp)

    注意 1.在socket_bind的时候ip地址不能真回环地址如127.0.0.1 2.server.php后台跑起来的时候 nohup php server.php > /var/tmp/a. ...

  2. Go语言中Socket通信TCP服务端

    1.用法: (1)定义远程IP地址.使用net.ResolveTCPAddr()方法,定义一个TCP地址,做为本机监听地址. (2)使用net.ListenTCP("tcp",lo ...

  3. socket通信(TCP和UDP)

    1.TCP 2.UDP

  4. 基于TCP和UDP的Socket通信

    TCP的Socket通信 TCP是面向连接的,安全的协议,它是一对一的关系 server client 上面只是单个客户端同服务器通信,可使用多线程编程实现多个客户端的通信 UDP的Socket通信 ...

  5. IOS 基于TCP的socket通信详解(原创)

    最近在整理通信层相关知识,这篇文章是边整理边写的,有些地方可能不够准确,还请各位路过的大牛专家指出来.这次整理的socket通信是基于TCP的,实现方式是GCD形式,以下记录的都是些理论知识,方便自己 ...

  6. 网络编程之Socket的TCP协议实现客户端与客户端之间的通信

    我认为当你学完某个知识点后,最好是做一个实实在在的小案例.这样才能更好对知识的运用与掌握 如果你看了我前两篇关于socket通信原理的入门文章.我相信对于做出我这个小案列是完全没有问题的!! 既然是小 ...

  7. TCP Socket通信详细过程

    下面这篇文章是参考"骏马金龙"博客中 不可不知的socket和TCP连接过程 https://www.cnblogs.com/f-ck-need-u/p/7623252.html ...

  8. C++写Socket——TCP篇(0)建立连接及双方传输数据

    满山的红叶--飘落之时-- 最近接触了点关于用C++写socket的东西,这里总结下. 这里主要是关于TCP的,TCP的特点什么的相关介绍在我另一篇博文里,所以这里直接动手吧. 我们先在windows ...

  9. Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)

    转载地址:http://blog.csdn.net/mad1989/article/details/9147661 ZERO.前言 有关通信原理内容是在网上或百科整理得到,代码部分为本人所写,如果不当 ...

随机推荐

  1. [js]js中回调函数

    //回调函数: 把一个函数当参数传给另个函数 /* function f1() { console.log('f1'); } function f2(f) { f(); console.log(1); ...

  2. crontab 详解

    1.crontab文件格式  {minute} {hour} {day-of-month} {month} {day-of-week} {full-path-to-shell-script} ● mi ...

  3. 9个Linux系统常用监控命令

    我们的系统一旦上线跑起来我们自然希望它一直相安无事,不要宕机,不要无响应,不要慢腾腾的.但是这不是打开机器电源然后放任不管就可以得到的.所以我们要监视系统的运行状况,发现问题及时处理. 对于系统和网络 ...

  4. log4j.properties配置详解与实例-全部测试通过[转]

    最近使用log4j写log时候发现网上的写的都是千篇一律,写的好的嘛不全,写的全一点的嘛没有一点格式,看着累.这里把网上收集到的整理了一下,并且全部都在机器上测试成功了.这么好的文档估计没有了吧? # ...

  5. MVC 下 JsonResult 的使用方法(JsonRequestBehavior.AllowGet)

    MVC 默认 Request 方式为 Post. actionpublic JsonResult GetPersonInfo(){var person = new{Name = "张三&qu ...

  6. Dockerfile详解(一)

    Dockerfile 用于自动化构建一个docker镜像.Dockerfile里有 CMD 与 ENTRYPOINT 两个功能咋看起来很相似的指令,开始的时候觉得两个互用没什么所谓,但其实并非如此: ...

  7. Cocos Creator 为Button添加事件的两种方法

    Button添加事件 Button 目前只支持 Click 事件,即当用户点击并释放 Button 时才会触发相应的回调函数.通过脚本代码添加回调方法一这种方法添加的事件回调和使用编辑器添加的事件回调 ...

  8. Deeplab v3+的结构代码简要分析

    添加了解码模块来重构精确的图像物体边界.对比如图 deeplab v3+采用了与deeplab v3类似的多尺度带洞卷积结构ASPP,然后通过上采样,以及与不同卷积层相拼接,最终经过卷积以及上采样得到 ...

  9. oauth2.0学习笔记(摘抄简化)

    大量摘抄白话简明教程. 附:可以参考<RFC6749协议中文版及oauth2.0>文档 一.OAuth 白话简明教程 1.简述 http://www.cnblogs.com/Ceri/p/ ...

  10. python读取大文件

    最近在学习python的过程中接触到了python对文件的读取.python读取文件一般情况是利用open()函数以及read()函数来完成: f = open(filename,'r') f.rea ...