linux下socket编程基础
- 格式:pdf
- 大小:222.79 KB
- 文档页数:12
Linux的SOCKET编程详解1. 网络中进程之间如何通信进程通信的概念最初来源于单机系统。
由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如UNIX BSD有:管道(pipe)、命名管道(named pipe)软中断信号(signal)UNIX system V有:消息(message)、共享存储区(shared memory)和信号量(semaphore)等.他们都仅限于用在本机进程之间通信。
网间进程通信要解决的是不同主机进程间的相互通信问题(可把同机进程通信看作是其中的特例)。
为此,首先要解决的是网间进程标识问题。
同一主机上,不同进程可用进程号(process ID)唯一标识。
但在网络环境下,各主机独立分配的进程号不能唯一标识该进程。
例如,主机A赋于某进程号5,在B机中也可以存在5号进程,因此,“5号进程”这句话就没有意义了。
其次,操作系统支持的网络协议众多,不同协议的工作方式不同,地址格式也不同。
因此,网间进程通信还要解决多重协议的识别问题。
其实TCP/IP协议族已经帮我们解决了这个问题,网络层的―ip地址‖可以唯一标识网络中的主机,而传输层的―协议+端口‖可以唯一标识主机中的应用程序(进程)。
这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。
使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。
就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说―一切皆s ocket‖。
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
在Linux下,可以使用C语言中的socket编程来判断一个端口是否已经关闭。
以下是一个简单的示例代码:c复制代码#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>int main(int argc, char *argv[]) {int sockfd;struct sockaddr_in serv_addr;char buffer[1024];int n;if (argc != 2) {fprintf(stderr, "Usage: %s <port>\n", argv[0]);exit(EXIT_FAILURE);}sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {perror("socket");exit(EXIT_FAILURE);}memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = INADDR_ANY;serv_addr.sin_port = htons(atoi(argv[1])); // 转换为网络字节序if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {perror("bind");exit(EXIT_FAILURE);}if (listen(sockfd, 10) < 0) {perror("listen");exit(EXIT_FAILURE);}while (1) {n = sizeof(serv_addr);int connfd = accept(sockfd, (struct sockaddr *)&serv_addr, &n);if (connfd < 0) {perror("accept");exit(EXIT_FAILURE);}printf("Accept connection from %s:%d\n", inet_ntoa(serv_addr.sin_addr),ntohs(serv_addr.sin_port));close(connfd); // 关闭连接,判断端口是否关闭成功}}这个程序创建了一个TCP服务器,监听指定的端口。
linuxc之解决使用socket函数返回为0的问题
1、问题:
在 linux 平台下写socket,实现简单的tcp通信,服务端第一次调用 socket函数返回 0
2、找原因:
我的代码是这样写的
if ((server_sockfd = socket(AF_INET,SOCK_STREAM, 0) < 0));
特么总是返回0,日了狗
自找方法一:
到网上找为什么socket函数返回0,5分钟过去,没反应
自找方法二:
到网上找linux socket tcp编程
然后得到代码,然后输入终端测试,发现socket返回是3,日了狗,然后再去缩小范围,只执行2行代码,一行实现socket,一行打印结果,依然是3,日了狗,然后再把自己
写的代码也只执行这2行,我插,依然是0,奔溃了,难道socket 还受终端影响,不应该啊,然后果断问旁边做服务端开发的,当然也是搞安卓的,然后我让他看的时候,发现代码写错,那个< 写错位置了,尼玛,3 < 0 否,然后把0给了这个server_sockfd 为0,又因为0 不小于 0,所以代码往下执行
if ((server_sockfd = socket(AF_INET,SOCK_STREAM, 0)) < 0);
3、总结
以后千万不要犯这种傻逼问题,代码要写好。
Linux下的CSocket编程--server端的简单⽰例Linux下的C Socket编程(三)server端的简单⽰例经过前⾯的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的⼀个端⼝上⾯去。
绑定socket到⼀个端⼝上bind()函数可以将socket绑定到⼀个端⼝上,client可以通过向这个端⼝发起请求,端⼝对应的socket便会与client端的socket连接。
#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/socket.h>#include<arpa/inet.h>int main() {int socket_desc;struct sockaddr_in server;socket_desc = socket(AF_INET, SOCK_STREAM, 0);if (-1 == socket_desc) {perror("cannot create socket");exit(1);}// 监听服务器⾃⾝server.sin_addr.s_addr = INADDR_ANY;server.sin_family = AF_INET;server.sin_port = htons(8888);// 绑定到端⼝if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) {perror("cannot bind error");exit(1);}printf("bind success");close(socket_desc);return 0;}对于server.sin_addr.s_addr的更多信息可以参考通过将socket绑定到⼀个确定的端⼝上,我们接下来要做的便是接收这个端⼝下的所有数据。
Linux下C语言的socket函数解析socketsocket()我们使用系统调用socket()来获得文件描述符:#include#includeint socket(int domain,int type,int protocol);第一个参数domain设置为“AF_INET”。
第二个参数是套接口的类型:SOCK_STREAM或SOCK_DGRAM。
第三个参数设置为0。
系统调用socket()只返回一个套接口描述符,如果出错,则返回-1。
bind()一旦你有了一个套接口以后,下一步就是把套接口绑定到本地计算机的某一个端口上。
但如果你只想使用connect()则无此必要。
下面是系统调用bind()的使用方法:#include#includeintbind(int sockfd,struct sockaddr*my_addr,int addrlen);第一个参数sockfd是由socket()调用返回的套接口文件描述符。
第二个参数my_addr是指向数据结构sockaddr的指针。
数据结构sockaddr中包括了关于你的地址、端口和IP地址的信息。
第三个参数addrlen可以设置成sizeof(structsockaddr)。
下面是一个例子:#include#include#include#define MYPORT 3490main(){int sockfd;struct sockaddr_inmy_addr;sockfd=socket(AF_INET,SOCK_STREAM,0);/*do someerror checking!*/my_addr.sin_family=AF_INET;/*hostbyteorder*/my_addr.sin_port=htons(MYPORT);/*short,network byte order*/my_addr.sin_addr.s_addr=inet_addr("132.241.5.10");bzero(&(my_addr.sin_zero),8);/*zero the rest of the struct*//*don't forget your error checking for bind():*/bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr));...如果出错,bind()也返回-1。
Linux中的Socket是一种用于网络通信的编程接口,它允许进程通过网络进行数据传输。
Socket在Linux内核中的实现涉及到多个组件和原理。
1. 网络协议栈:Linux内核中的网络协议栈负责处理网络通信的各个层次,包括物理层、数据链路层、网络层和传输层。
Socket通过网络协议栈与网络进行交互。
2. 套接字数据结构:在Linux内核中,套接字(Socket)被实现为一种数据结构,用于表示网络连接。
套接字数据结构包含了连接的相关信息,如IP地址、端口号等。
3. 文件描述符:在Linux中,套接字被视为一种文件,因此每个套接字都有一个对应的文件描述符。
通过文件描述符,进程可以对套接字进行读写操作。
4. 网络设备驱动程序:Linux内核中的网络设备驱动程序负责处理网络设备的底层操作,如发送和接收数据包。
套接字通过网络设备驱动程序与网络设备进行通信。
5. 网络协议处理:当进程通过套接字发送或接收数据时,Linux内核会根据套接字的协议类型(如TCP或UDP)进行相应的协议处理。
这包括建立连接、数据分片、错误检测等操作。
6. 系统调用:在用户空间中,进程通过系统调用(如socket、bind、connect等)来创建和操作套接字。
系统调用会触发内核中相应的函数,完成套接字的创建和操作。
总的来说,Linux内核中的Socket实现涉及到网络协议栈、套接字数据结构、文件描述符、网络设备驱动程序、网络协议处理和系统调用等多个组件和原理。
这些组件和原理共同工作,使得进程能够通过套接字进行网络通信。
{"code":0,"msg":"请求出现异常","data":{}}。
LinuxCSocket编程发送结构体、⽂件详解及实例利⽤Socket发送⽂件、结构体、数字等,是在Socket编程中经常需要⽤到的。
由于Socket只能发送字符串,所以可以使⽤发送字符串的⽅式发送⽂件、结构体、数字等等。
本⽂:1.memcpy Copy block of memory。
内存块拷贝函数,该函数是标准库函数,可以进⾏⼆进制拷贝数据。
函数原型: void * memcpy ( void * destination, const void * source, size_t num ); 函数说明:从source指向的地址开始拷贝num个字节到以destination开始的地址。
其中destination与source指向的数据类型⽆关。
2.Socket传输 使⽤memcpy将⽂件、结构体、数字等,可以转换为char数组,之后进⾏传输,接收⽅在使⽤memcpy将char数组转换为相应的数据。
下⾯的程序使⽤Socket传输结构体数据,由客户端传输给服务器端。
传输的结构体为:typedef struct{int ab;int num[1000000];}Node;服务器代码:1 #include<netinet/in.h>2 #include<sys/types.h>3 #include<sys/socket.h>4 #include<stdio.h>5 #include<stdlib.h>6 #include<string.h>78#define HELLO_WORLD_SERVER_PORT 66669#define LENGTH_OF_LISTEN_QUEUE 2010#define BUFFER_SIZE 10241112 typedef struct13 {14int ab;15int num[1000000];16 }Node;1718int main(int argc, char **argv)19 {20// set socket's address information21struct sockaddr_in server_addr;22 bzero(&server_addr, sizeof(server_addr));23 server_addr.sin_family = AF_INET;24 server_addr.sin_addr.s_addr = htons(INADDR_ANY);25 server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);2627// create a stream socket28int server_socket = socket(PF_INET, SOCK_STREAM, 0);29if (server_socket < 0)30 {31 printf("Create Socket Failed!\n");32 exit(1);33 }3435//bind36if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)))37 {38 printf("Server Bind Port: %d Failed!\n", HELLO_WORLD_SERVER_PORT);39 exit(1);40 }4142// listen43if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE))45 printf("Server Listen Failed!\n");46 exit(1);47 }4849while(1)50 {51struct sockaddr_in client_addr;52 socklen_t length = sizeof(client_addr);5354int new_server_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length);55if (new_server_socket < 0)56 {57 printf("Server Accept Failed!\n");58break;59 }6061 Node *myNode=(Node*)malloc(sizeof(Node));6263int needRecv=sizeof(Node);64char *buffer=(char*)malloc(needRecv);65int pos=0;66int len;67while(pos < needRecv)68 {69 len = recv(new_server_socket, buffer+pos, BUFFER_SIZE, 0);70if (len < 0)71 {72 printf("Server Recieve Data Failed!\n");73break;74 }75 pos+=len;7677 }78 close(new_server_socket);79 memcpy(myNode,buffer,needRecv);80 printf("recv over ab=%d num[0]=%d num[999999]=%d\n",myNode->ab,myNode->num[0],myNode->num[999999]);81 free(buffer);82 free(myNode);83 }84 close(server_socket);8586return0;87 }View Code客户端代码:1 #include <sys/types.h>2 #include <sys/socket.h> // 包含套接字函数库3 #include <stdio.h>4 #include <netinet/in.h> // 包含AF_INET相关结构5 #include <arpa/inet.h> // 包含AF_INET相关操作的函数6 #include <unistd.h>7 #include <string.h>8 #include <stdlib.h>9 #include <fcntl.h>10 #include <sys/shm.h>11 #include <pthread.h>1213#define MYPORT 666614#define BUFFER_SIZE 10241516 typedef struct17 {18int ab;19int num[1000000];20 }Node;2122int main()23 {24///sockfd25int sock_cli = socket(AF_INET,SOCK_STREAM, 0);2627struct sockaddr_in servaddr;28 memset(&servaddr, 0, sizeof(servaddr));29 servaddr.sin_family = AF_INET;30 servaddr.sin_port = htons(MYPORT);31 servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");3233if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)35 perror("connect");36 exit(1);37 }3839 Node *myNode=(Node*)malloc(sizeof(Node));40 myNode->ab=123;41 myNode->num[0]=110;42 myNode->num[999999]=99;4344int needSend=sizeof(Node);45char *buffer=(char*)malloc(needSend);46 memcpy(buffer,myNode,needSend);4748int pos=0;49int len=0;50while(pos < needSend)51 {52 len=send(sock_cli, buffer+pos, BUFFER_SIZE,0); 53if(len <= 0)54 {55 perror("ERRPR");56break;57 }58 pos+=len;59 }60 free(buffer);61 free(myNode);62 close(sock_cli);63 printf("Send over!!!\n");64return0;65 }View Code服务器端执⾏输出:。