用Socket编写CS结构程序

合集下载

简单的CS通信

简单的CS通信

利用socket技术完成c/s通信socket服务器端函数<?php// 设置主机名称和端口号$host = "127.0.0.1";$port = 1234567;// 设置超时时间set_time_limit(0);// 创建Socket实例$commonProtocol = getprotobyname("tcp");$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol)ordie("Could not createsocket\n");//绑定Socket到端口socket_bind($socket, $host, $port) or die("Could not bind to socket\n"); // 开始监听链接socket_listen($socket) or die("Could not set up socket listener\n"); //编写服务端发送客户端的消息$info = "欢迎光临三扬科技!\n\r";while(true){$conn = socket_accept($socket);printf("Socket 连接成功!\r\n");if($info != ""){printf("向客户端发送消息.....\r\n");echo @socket_write($conn, $info, strlen($info))."\n\r";printf("Socket发送的信息是:".$info."\r\n");}else{printf("没有可以发送的消息!\r\n");}socket_close($conn);printf("关闭 socket服务!\r\n\r\n");}socket_close($socket);?>注意:socket服务器应该使用cmd命令行的php.exe进行调用,不要直接请求服务器的页面,否则不能正确的启动服务器端的socket服务socket建立客户端socket客户端函数介绍Client.php<?php//服务器名称和端口$hostAddress ="127.0.0.1";$hostPort =1234567;//创建Socket实例$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);//连接服务器$conn = socket_connect($socket,$hostAddress, $hostPort);if ($conn) {echo "服务器连接成功,以下是服务器应答信息。

c语言websockets例子

c语言websockets例子

c语言websockets例子摘要:1.引言2.C语言WebSocket概述3.使用C语言实现WebSocket的例子4.总结正文:WebSocket是一种在单个TCP连接上进行全双工通信的协议,它允许服务器与客户端之间进行双向通信。

WebSocket在Web开发中得到了广泛的应用,而在C语言中实现WebSocket则需要使用一些第三方库。

以下是使用C语言实现WebSocket的一个简单例子。

这个例子基于libwebsockets库,它是一个用于实现WebSocket协议的C库。

首先,需要安装libwebsockets库。

在Ubuntu系统上,可以使用以下命令进行安装:```sudo apt-get install libwebsockets-dev```接下来,创建一个名为`websocket_example.c`的C文件,并将以下代码粘贴到文件中:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <websockets.h>#define PORT 8080#define BUFFER_SIZE 1024int main() {struct libwebsocket_context *context;struct libwebsocket *wsi;struct libwebsocket_message msg;char buffer[BUFFER_SIZE];// 初始化libwebsocketslibwebsocket_init();libwebsocket_set_log_level(LL_DEBUG, NULL);// 创建WebSocket上下文context = libwebsocket_create_context(NULL);// 创建WebSocket服务器wsi = libwebsocket_server_init(context, PORT);// 循环处理WebSocket请求while (1) {// 等待新的WebSocket连接或消息libwebsocket_service(context, 0);// 处理接收到的消息if (libwebsocket_read(wsi, &msg, sizeof(msg)) == LWS_SSL_CAPABLE) {// 将接收到的消息打印到控制台printf("Received message: %s", msg.data);// 发送消息回客户端strcpy(buffer, "Hello, client!");libwebsocket_write(wsi, buffer, strlen(buffer), LWS_WRITE_TEXT);}}// 关闭WebSocket服务器libwebsocket_server_destroy(wsi);// 销毁WebSocket上下文libwebsocket_context_destroy(context);// 清理libwebsocketslibwebsocket_destroy();return 0;}```接下来,使用以下命令编译C文件:```gcc websocket_example.c -o websocket_example -lwebsockets```编译完成后,运行生成的可执行文件:```./websocket_example```此时,WebSocket服务器已经启动,监听在8080端口。

基于CS模型简单的 socket例子

基于CS模型简单的 socket例子

从一个简单的基于C/S模型的TCP socket编程案例,其基本步骤如下:server client+++++++ ++++++++创建socket 创建socket+++++++ ++++++++| || || |+++++++ ++++++++地址赋值(地址赋值(自己的地址)服务器地址)+++++++ ++++++++| || || |++++++++ |用bind绑定|socket和地址|++++++++ || || |+++++++ |listen |+++++++ || ++++++++++| <------------------------------ connect 服务器| +++++++++++++++++ |accept |+++++++ || || +++++++++| recv 和send| 进行数据处理| ++++++++++++++++++ |用accept得到|的socket进行|recv 和send |+++++++++ || || |+++++++++ +++++++++ close socket close socket +++++++++ +++++++++根据以上步骤,服务器端的代码为[cpp]view plaincopy1.#include <stdio.h>2.#include <string.h>3.#include <sys/socket.h>4.#include <netinet/in.h>5.#include <stdlib.h>6.#include <syslog.h>7.#include <errno.h>8.#define MAX_LISTEN_NUM 59.#define SEND_BUF_SIZE 10010.#define RECV_BUF_SIZE 10011.#define LISTEN_PORT 101012.int main()13.{14.int listen_sock = 0;15.int app_sock = 0;16.struct sockaddr_in hostaddr;17.struct sockaddr_in clientaddr;18.int socklen = sizeof(clientaddr);19.char sendbuf[SEND_BUF_SIZE] = {0};20.char recvbuf[RECV_BUF_SIZE] = {0};21.int sendlen = 0;22.int recvlen = 0;23.int retlen = 0;24.int leftlen = 0;25.char *ptr = NULL;26. memset((void *)&hostaddr, 0, sizeof(hostaddr));27. memset((void *)&clientaddr, 0, sizeof(clientaddr));28. hostaddr.sin_family = AF_INET;29. hostaddr.sin_port = htons(LISTEN_PORT);30. hostaddr.sin_addr.s_addr = htonl(INADDR_ANY);31. listen_sock = socket(AF_INET, SOCK_STREAM, 0);32.if(listen_sock < 0)33. {34. syslog(LOG_ERR, "%s:%d, create socket failed", __FILE__, __LINE__);35. exit(1);36. }37.if(bind(listen_sock, (struct sockaddr *)&hostaddr, sizeof(hostaddr)) < 0)38. {39. syslog(LOG_ERR, "%s:%d, bind socket failed", __FILE__, __LINE__);40. exit(1);41. }42.if(listen(listen_sock, MAX_LISTEN_NUM) < 0)43. {44. syslog(LOG_ERR, "%s:%d, listen failed", __FILE__, __LINE__);45. exit(1);46. }47.while(1)48. {49. app_sock = accept(listen_sock, (struct sockaddr *)&clientaddr, &socklen);50.if(app_sock < 0)51. {52. syslog(LOG_ERR, "%s:%d, accept failed", __FILE__, __LINE__);53. exit(1);54. }55. sprintf(sendbuf, "welcome %s:%d here!/n", inet_ntoa(clientaddr.sin_addr.s_addr), clientaddr.sin_port);56.//send data57. sendlen = strlen(sendbuf) +1;58. retlen = 0;59. leftlen = sendlen;60. ptr = sendbuf;61.//while(leftlen)62. {63. retlen = send(app_sock, ptr, sendlen, 0);64.if(retlen < 0)65. {66.if(errno == EINTR)67. retlen = 0;68.else69. exit(1);70. }71. leftlen -= retlen;72. ptr += retlen;73. }74.//receive data75. recvlen = 0;76. retlen = 0;77. ptr = recvbuf;78. leftlen = RECV_BUF_SIZE -1;79.//do80. {81. retlen = recv(app_sock, ptr, leftlen, 0) ;82.if(retlen < 0)83. {84.if(errno == EINTR)85. retlen = 0;86.else87. exit(1);88. }89. recvlen += retlen;90. leftlen -= retlen;91. ptr += retlen;92. }93.//while(recvlen && leftlen);94. printf("receive data is : %s", recvbuf);95. close(app_sock);96. }97. close(listen_sock);98.99.return 0;100.101.102.}客户端代码为:[cpp]view plaincopy1.#include <stdio.h>2.#include <string.h>3.#include <sys/socket.h>4.#include <netinet/in.h>5.#include <syslog.h>6.#include <errno.h>7.#include <stdlib.h>8.#define MAX_LISTEN_NUM 59.#define SEND_BUF_SIZE 10010.#define RECV_BUF_SIZE 10011.#define SERVER_PORT 101012.int main()13.{14.int sock_fd = 0;15.char recvbuf[RECV_BUF_SIZE] = {0};16.char sendbuf[SEND_BUF_SIZE] = {0};17.int recvlen = 0;18.int retlen = 0;19.int sendlen = 0;20.int leftlen = 0;21.char *ptr = NULL;22.struct sockaddr_in ser_addr;23.24. memset(&ser_addr, 0, sizeof(ser_addr));25. ser_addr.sin_family = AF_INET;26. inet_aton("127.0.0.1", (struct in_addr *)&ser_addr.sin_addr);27. ser_addr.sin_port = htons(SERVER_PORT);28. sock_fd = socket(AF_INET, SOCK_STREAM, 0);29.if(sock_fd < 0)30. {31. syslog(LOG_ERR, "%s:%d, create socket failed", __FILE__, __LINE__);32. exit(1);33. }34.if(connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) < 0)35. {36. syslog(LOG_ERR, "%s:%d, connect socket failed", __FILE__, __LINE__);37. exit(1);38. }39.//receive data40. recvlen = 0;41. retlen = 0;42. ptr = recvbuf;43. leftlen = RECV_BUF_SIZE -1;44.//do45. {46. retlen = recv(sock_fd, ptr, leftlen, 0) ;47.if(retlen < 0)48. {49.if(errno == EINTR)50. retlen = 0;51.else52. exit(1);53. }54. recvlen += retlen;55. leftlen -= retlen;56. ptr += retlen;57. }58.//while(recvlen && leftlen);59. printf("receive data is : %s", recvbuf);60. sprintf(sendbuf, "hello server/n");61.//send data62. sendlen = strlen(sendbuf) +1;63. retlen = 0;64. leftlen = sendlen;65. ptr = sendbuf;66.// while(leftlen)67. {68. retlen = send(sock_fd, ptr, sendlen, 0);69.if(retlen < 0)70. {71.if(errno == EINTR)72. retlen = 0;73.else74. exit(1);75. }76. leftlen -= retlen;77. ptr += retlen;78. }79. close(sock_fd);80.81.}现在一个简单的使用tcp的socket通信的例子已经完成了,这里有几个需要说明的问题1)头文件:sys/socket.h 包含了socket相关的函数,如socket,send 和recv,以及struct sockaddr 等netinet/in.h 包含了地址结构,如struct sockaddr_inerrno.h 包含了errno 和EINTRsyslog.h 包含了syslog相关的信息,其打印结果在/var/log/messages里面2)socket地址对于IPv4来说,其地址用的是struct sockaddr_in,具体结构如下[cpp]view plaincopy1.struct in_addr {2. in_addr_t s_addr; /* 32-bit IPv4 address */3./* network byte ordered */4.};5.6.struct sockaddr_in {7. uint8_t sin_len; /* length of structure (16) */8. sa_family_t sin_family; /* AF_INET */9. in_port_t sin_port; /* 16-bit TCP or UDP port number */10./* network byte ordered */11.struct in_addr sin_addr; /* 32-bit IPv4 address */12./* network byte ordered */13.char sin_zero[8]; /* unused */14.};其中sin_len我们一般不关注,也不填(只有在使用routing socket的时候才用到,被内核用来处理各种协议簇的地址结构)。

C语言SOCKET编程超级完整

C语言SOCKET编程超级完整

介绍Socket 编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect() 前的bind() 的结构而不知所措?等等…好在我已经将这些事完成了,我将和所有人共享我的知识了。

如果你了解 C 语言并想穿过网络编程的沼泽,那么你来对地方了。

--------------------------------------------------------------------------------读者对象这个文档是一个指南,而不是参考书。

如果你刚开始 socket 编程并想找一本入门书,那么你是我的读者。

但这不是一本完全的 socket 编程书。

--------------------------------------------------------------------------------平台和编译器这篇文档中的大多数代码都在 Linux 平台PC 上用 GNU 的gcc 成功编译过。

而且它们在 HPUX平台上用 gcc 也成功编译过。

但是注意,并不是每个代码片段都独立测试过。

--------------------------------------------------------------------------------目录:1) 什么是套接字?2) Internet 套接字的两种类型3) 网络理论4) 结构体5) 本机转换6) IP 地址和如何处理它们7) socket()函数8) bind()函数9) connect()函数10) listen()函数11) accept()函数12) send()和recv()函数13) sendto()和recvfrom()函数14) close()和shutdown()函数15) getpeername()函数16) gethostname()函数17) 域名服务(DNS)18) 客户-服务器背景知识19) 简单的服务器20) 简单的客户端21) 数据报套接字Socket22) 阻塞23) select()--多路同步I/O24) 参考资料--------------------------------------------------------------------------------什么是 socket?你经常听到人们谈论着“socket”,或许你还不知道它的确切含义。

JAVA实现CS结构小程序

JAVA实现CS结构小程序

JAVA实现CS结构⼩程序程序功能:客户端向服务器发送⼀个本地磁盘中的⽂件, 服务器程序接受后保存在其他位置.客户端实现步骤:1. 创建⼀个客户端对象Socket,构造⽅法中绑定服务器的IP地址和端⼝号2. 使⽤Socket对象中的⽅法 getOutputSteam()获取⽹络字节输出流OutputStream对象3. 使⽤字节输出流OutputStream对象中的write()⽅法,给服务器发送数据4. 使⽤Socket对象中的getInputStream()获取⽹络字节输⼊流InputStream()对象 5. 使⽤⽹络字节输⼊流InputStream对象中的read()⽅法,读取服务器回写的数据.6. 释放Socket资源.1import java.io.*;2import .Socket;34public class TCPClient {5public static void main(String[] args) throws IOException {6//1.创建⼀个客户端对线Socket,构造⽅法中绑定服务器的IP地址和端⼝号7 Socket socket = new Socket("127.0.0.1",8888);8// Socket socket = new Socket("192.168.15.132",8888);9//2.使⽤Socket对象中的⽅法getOutputStream(0获取⽹络字节输出流OutputSteam对象10//这个流是个⽹络流,指向了服务器11 OutputStream os = socket.getOutputStream();12 File f = new File("E:\\图⽚\\桌⾯图⽚\\宋民国\\222.jpg");13 FileInputStream fis = new FileInputStream(f);14byte[] bs = new byte[1024];15int len;16while((len=fis.read(bs))!=-1)17 {18//3.使⽤字节输出流OutputSteam对象中的⽅法write,给服务器发送数据19 os.write(bs,0,len);20 }21//告诉服务器关闭输出22 socket.shutdownOutput();23 fis.close();2425//4.使⽤Socket对象中的⽅法getInputSteam()获取⽹络字节输⼊流InputSteam()对象26 InputStream is = socket.getInputStream();27//5.使⽤⽹络字节输⼊流InputSteam对象中的⽅法read,读取服务器回写的数据28byte[] list = new byte[1024];29int len1 = is.read(list);30 String str1 = new String(list,0,len1);31//6.释放资源(Socket)32 System.out.println(str1);33 socket.close();//只⽤关socket就⾏了343536 }37 }服务器端实现步骤:1. 创建⼀个服务器对ServerSocket对象和指定的端⼝号⼀致.2. 使⽤ServerSocket对象中的accept⽅法,获取请求的客户端对象Socket3. 使⽤Socket对象中的getInputSream()⽅法4. 使⽤⽹络字节输⼊流InputStream对象中的read()⽅法5. 使⽤Socket对象中的getoutputStream()⽅法6. 使⽤⽹络字节输出流OutputSteam对象中的write()⽅法7. 释放资源.1import java.io.*;2import .ServerSocket;3import .Socket;4import java.util.Random;56public class TCPServer {7public static void main(String[] args) throws IOException {89//method01();10 method02();1112 }13public static void method02() throws IOException{14// 1.创建⼀个服务器对ServerSocket对象和指定的端⼝号要⼀致.15 ServerSocket serverSocket = new ServerSocket(8888);16while(true) {17//2.使⽤ServerSocket对象中的的⽅法accept,获取到请求的客户端对象Scoket18// 创建多线程,提⾼可以同时与多个客户端进⾏数据的传输,提⾼效率19 Socket socket = serverSocket.accept();//阻塞(如果没有客户端连接,程序会停⽌在这个地⽅) 20new Thread(() -> {21try {22//获得客户端Socket对象23//给保存的⽂件设置随机名,避免覆盖24long time = System.currentTimeMillis();25//3.使⽤Socket对象中的⽅法getInputSteam() 获得输⼊流26 InputStream is = socket.getInputStream();27 FileOutputStream fos = new FileOutputStream(new File("C:\\123\\123", time + ".jpg")); 28byte[] list = new byte[1024];29int len;30//4.使⽤⽹络字节输⼊流InputStream对象中的read()⽅法31while ((len = is.read(list)) != -1) {32 fos.write(list, 0, len);33 }34 fos.close();35//5. 使⽤Socket对象中的getoutputStream()⽅法获得输出流36 OutputStream os = socket.getOutputStream();37//6.使⽤⽹络字节输出流OutputSteam对象中的write()⽅法38 os.write("你好,图⽚传输完毕".getBytes());3940//7. 释放资源41 socket.close();42 } catch (IOException e) {43 e.printStackTrace();44 }45 }).start();4647 }48 }49public static void method01() throws IOException {5051//1.创建⼀个服务器对ServerSocket对象和系统指定的端⼝号要⼀致.52 ServerSocket server = new ServerSocket(8888);53/*让服务器⼀直处于监听状态(死循环accept⽅法)54 * 有⼀个客户端上传⽂件,就保存⼀个⽂件.55 * */56while (true){57/* 在步骤1 与步骤2 之间会卡主, 等待客户端连接,连接了才会进⾏下⼀步*/5859//2.使⽤ServerSocket对象中的的⽅法accept,获取到请求的客户端对象Scoket60 Socket socket = server.accept();616263//3.使⽤Socket对象中的⽅法getInputSteam()64// 得到⼀个输⼊流,该输⼊流就可以调⽤read()⽅法65 InputStream is = socket.getInputStream();66// 4.使⽤⽹络字节输⼊流InptuSteam对象中的read6768//⽂件夹在是定⽂件夹下创建⽂件69 File dir = new File("C:\\123\\123");70/* //⾃动⽣成⼀个时间戳,⾃动⽣成⽂件名,利⽤毫秒值当做⽂件名71 * ⽤System.currentTimeMilis()⽅法获取当前系统的毫秒值,72 * 再加上⼀个随机数. 保证⽂件名是不重复的.73 * */74long time = System.currentTimeMillis();75 String filename =time+new Random().nextInt(1000)+"";76/*如果该⽂件夹不存在,则⽣成这个⽂件夹*/77if(!dir.exists()){78 dir.mkdirs();79 }80/**/81 FileOutputStream fos = new FileOutputStream(new File(dir,filename+".jpg"));8283 // FileOutputStream fos = new FileOutputStream(destination);84 byte[] bs = new byte[1024];85 int len;86 while((len=is.read(bs))!=-1)87 {88 fos.write(bs,0,len);89 }90 //告诉91 fos.close();929394 //5.使⽤Socket对象中的⽅法 getoutputSteam 回写收到了就谢谢.95 //利⽤⽹络指向客户端.往客户端回写数据.96 OutputStream os = socket.getOutputStream();97 //都是字节流,转换为字节再写回去.98 os.write("收到谢谢".getBytes());99 /*socket.close();100101 server.close();*/102103 }104105106107 }108 }运⾏结果:。

windows socket编程c语言

windows socket编程c语言

windows socket编程c语言Windows Socket编程是一种用于在Windows操作系统上进行网络通信的编程技术。

通过使用Windows Socket API,开发人员可以使用C语言来创建网络应用程序,实现网络通信的各种功能。

Windows Socket编程的主要目标是建立和管理网络连接。

它提供了一套函数和数据结构,用于创建和管理套接字(Socket),这是网络通信的基本单元。

套接字可以用于在客户端和服务器之间传输数据,可以是TCP套接字,也可以是UDP套接字。

在Windows Socket编程中,首先需要创建一个套接字。

套接字可以通过调用socket函数来创建,该函数接受三个参数:地址族(AF_INET或AF_INET6),套接字类型(SOCK_STREAM或SOCK_DGRAM)和协议(通常为0)。

创建套接字后,可以使用bind函数将套接字绑定到特定的IP地址和端口号。

一旦套接字被创建和绑定,就可以使用connect函数在客户端和服务器之间建立连接。

对于TCP套接字,可以使用listen函数开始监听连接请求,并使用accept函数接受客户端的连接。

对于UDP套接字,不需要建立连接,可以直接发送和接收数据。

一旦连接建立成功,就可以使用send和recv函数在套接字之间传输数据。

send函数用于将数据发送到远程主机,而recv函数用于接收远程主机发送的数据。

可以使用这两个函数进行双向通信,发送和接收数据。

Windows Socket编程还提供了一些其他的函数和数据结构,用于处理网络通信中的其他问题。

例如,可以使用getaddrinfo函数解析主机名和服务名,以获取对应的IP地址和端口号。

可以使用select函数在多个套接字之间进行多路复用,以实现并发处理。

可以使用ioctlsocket函数设置套接字的属性,例如非阻塞模式。

除了基本的网络通信功能,Windows Socket编程还支持一些高级功能,例如多线程和异步操作。

c 标准库 socket

c 标准库 socket

c 标准库 socketC 标准库中的socket。

在C语言中,socket是一个非常重要的概念,它提供了一种通信机制,使得不同的程序能够在网络上进行数据交换。

在C标准库中,我们可以通过使用socket 来实现网络编程,实现客户端和服务器之间的通信。

本文将介绍C标准库中socket 的基本概念、使用方法以及一些常见问题的解决方案。

首先,我们需要了解什么是socket。

Socket是一种通信机制,它允许不同的程序在网络上进行数据交换。

在C标准库中,我们可以通过包含<sys/socket.h>头文件来使用socket相关的函数和数据结构。

使用socket编程时,我们需要创建一个socket对象,并通过bind、listen、accept等函数来建立和管理网络连接。

接下来,我们来看一下如何在C标准库中使用socket。

首先,我们需要创建一个socket对象,可以通过调用socket函数来实现。

该函数接受三个参数,分别是地址族、套接字类型和协议。

例如,我们可以通过调用socket(AF_INET,SOCK_STREAM, 0)来创建一个基于IPv4协议的流式套接字。

接着,我们可以通过调用bind函数来绑定套接字到一个特定的地址和端口。

然后,我们可以通过调用listen函数来监听连接请求,并通过accept函数来接受客户端的连接。

最后,我们可以通过read和write函数来进行数据的读写操作。

在实际的网络编程中,我们可能会遇到一些常见的问题,比如如何处理并发连接、如何处理网络错误等。

针对这些问题,我们可以通过使用多线程或多进程来处理并发连接,可以通过设置超时时间来处理网络错误。

另外,我们还可以通过使用非阻塞IO来提高程序的性能,通过使用select函数来实现多路复用等技术来优化网络编程的性能和稳定性。

总结一下,C标准库中的socket提供了一种通信机制,使得不同的程序能够在网络上进行数据交换。

cs架构简单介绍

cs架构简单介绍

cs架构简单介绍c/s架构即客户端/服务端架构(想⼴义点)学习socket(套接字)是为了c/s架构服务的,⽽这之前要学ois七层(相当于全世界⼈想通讯必须规定⽤英语/linhaifeng/articles/5937962.html)简单理解⼀下ois七层(也就是⼀种协议,世界上所有计算机中的不同应⽤程序之间的⼀种通⽤交流语⾔):物理层,数据链路层,⽹络层,传输层,(会话层,表⽰层,应⽤层)举个例⼦,⾸先物理层很好理解,是通信的介质(电缆,线路,⽆线等等)假设将⽹络通讯⽐作不同教室之间⼈的通讯,原始的⼈与⼈之间⽤吼(即⼴播),只要知道每个⼈名字(MAC地址)吼⼀声就可以。

计算机A与计算机B通讯,计算机A产⽣⼀串0101,没有任何意义,数据链路层将它们分组,附上MAC地址,吼原则上,如果世界上所有计算机在⼀个教室中,到这⼀层,问题解决。

可是实际不可能这样,没这么⼤的教室,它们在不同的教室中。

所以如果A,B不在同⼀个教室,⾸先还得知道它们所在的教室号,这时候⽹络层诞⽣,IP地址(协议)出现。

有了这两个,A,B通讯没问题了。

可是我想要的是计算机A上的QQ与计算机B上⾯的QQ通讯,⽽不是与暴风什么的。

所以还得锁定电脑上的不同程序,⽽每个程序与端⼝绑定,基于端⼝有TCP/UDP协议。

(因为IP是绑定在⽹卡上(mac)的,所以有时候说ip标识⼀台计算机是隐含了这层意思)⽽每次这样通讯也太⿇烦了,所以有⼈将TCP/IP协议封装,也就是将应⽤层(⼴义)以下封装,留⼏个接⼝调⽤,这样产⽣了socket协议。

说⽩了基于socket协议也就是基于IOS协议因此,客户端是⼀个程序,服务端是⼀个程序,两种通讯是要基于IOS协议,这⾥相当于简化,基于SOCKET(其实套接字有基于⽹络的,还有基于⽂件的,这⾥相当于基于⽹络的)下⾯是⼀套简陋的客户端与服务端:socket客户端:1import socket23 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)45 phone.connect(('127.0.0.1',8000)) # 拨电话 , IP只能绑定⾃⼰电脑上的IP67# 必须⼆进制发收,不能直接发字符串8 phone.send('hello'.encode('utf-8')) # 假设发⼀个hello9 data = phone.recv(1024) # 接收服务器发来的消息10print('收到服务器的消息是: ',data)View Code这张图⽚帮助简单理解,下⾯是服务端:1import socket23'''4这段代码其实就是实现TCP的三次握⼿,数据通讯(每次发送都有ack回应,所以说是严密的),四次挥⼿5'''67 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET是基于⽹络的意思8 phone.bind(('127.0.0.1',8000)) # IP+端⼝,这⾥的IP地址必须是⾃⼰电脑的IP9 phone.listen(5) # 对多等多少个电话,相当于缓存⼤⼩1011print('---------------------------下⾯accept等待')1213 conn, addr = phone.accept() # 等电话,⼀旦有电话拿到电话连接与对⽅⼿机号,TCP背后做三次握⼿1415# 注意通讯是基于⽹络,也就是⼆进制通讯16 msg = conn.recv(1024) #收对⽅消息,1024代表收对⽅多少量消息17print('客户端发来的消息是: ',msg)181920 conn.send(msg.upper()) # 发消息2122 conn.close()23 phone.close()View Code。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

用socket编写C/S结构程序的流程图1.面向连接的套接字的系统调用时序图无连接协议的套接字调用时序图面向连接的应用程序流程图Socket编程实例代码实例中的服务器通过socket连接向客户端发送字符串"Hello, you are connected!"。

只要在服务器上运行该服务器软件,在客户端运行客户软件,客户端就会收到该字符串。

该服务器软件代码如下:#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/wait.h>#define SERVPORT 3333 /*服务器监听端口号*/#define BACKLOG 10 /* 最大同时连接请求数*/main(){intsockfd,client_fd; /*sock_fd:监听socket;client_fd:数据传输socket */ structsockaddr_inmy_addr; /* 本机地址信息*/structsockaddr_inremote_addr; /* 客户端地址信息*/if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("socket创建出错!"); exit(1);}my_addr.sin_family=AF_INET;my_addr.sin_port=htons(SERVPORT);my_addr.sin_addr.s_addr = INADDR_ANY;bzero(&(my_addr.sin_zero),8);if (bind(sockfd, (structsockaddr *)&my_addr, sizeof(structsockaddr)) == -1){perror("bind出错!");exit(1);}if (listen(sockfd, BACKLOG) == -1) {perror("listen出错!");exit(1);}while(1){sin_size = sizeof(structsockaddr_in);if ((client_fd = accept(sockfd, (structsockaddr *)&remote_addr, &sin_size)) == -1){perror("accept出错");continue;}printf("received a connection from %s ", inet_ntoa(remote_addr.sin_addr));if (!fork()){ /* 子进程代码段*/if (send(client_fd, "Hello, you are connected! ", 26, 0) == -1)perror("send出错!");close(client_fd);exit(0);}close(client_fd);}}服务器的工作流程是这样的:首先调用socket函数创建一个Socket,然后调用bind函数将其与本机地址以及一个本地端口号绑定,然后调用listen在相应的socket上监听,当accpet接收到一个连接服务请求时,将生成一个新的socket。

服务器显示该客户机的IP地址,并通过新的socket向客户端发送字符串"Hello,you are connected!"。

最后关闭该socket。

代码实例中的fork()函数生成一个子进程来处理数据传输部分,fork()语句对于子进程返回的值为0。

所以包含fork函数的if语句是子进程代码部分,它与if语句后面的父进程代码部分是并发执行的。

客户端程序代码如下:#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <netdb.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#define SERVPORT 3333#define MAXDATASIZE 100 /*每次最大数据传输量*/main(intargc, char *argv[]){intsock_fd, recvbytes;charbuf[MAXDATASIZE];structhostent *host;structsockaddr_inserv_addr;if(argc< 2){fprintf(stderr,"Please enter the server's hostname!\n");exit(1);}if((host=gethostbyname(argv[1])) == NULL){herror("gethostbyname出错!");exit(1);}if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("socket创建出错!");exit(1);}serv_addr.sin_family=AF_INET;serv_addr.sin_port=htons(SERVPORT);serv_addr.sin_addr = *((structin_addr *)host->h_addr);bzero(&(serv_addr.sin_zero),8);if(connect(sock_fd, (structsockaddr *)&serv_addr, sizeof(structsockaddr)) == -1) {perror("connect出错!");exit(1);}if((recvbytes=recv(sock_fd, buf, MAXDATASIZE, 0)) == -1){perror("recv出错!");exit(1);}buf[recvbytes] = '\0';printf("Received: %s",buf);close(sock_fd);}客户端程序首先通过服务器域名获得服务器的IP地址,然后创建一个socket,调用connect函数与服务器建立连接,连接成功之后接收从服务器发送过来的数据,最后关闭socket。

函数gethostbyname()是完成域名转换的。

由于IP地址难以记忆和读写,所以为了方便,人们常常用域名来表示主机,这就需要进行域名和IP地址的转换。

函数原型为:structhostent *gethostbyname(const char *name);函数返回为hosten的结构类型,它的定义如下:structhostent{char *h_name; /* 主机的官方域名*/char **h_aliases; /* 一个以NULL结尾的主机别名数组*/inth_addrtype; /* 返回的地址类型,在Internet环境下为AF-INET */inth_length; /* 地址的字节长度*/char **h_addr_list; /* 一个以0结尾的数组,包含该主机的所有地址*/};#define h_addrh_addr_list[0] /*在h-addr-list中的第一个地址*/当gethostname()调用成功时,返回指向structhostent的指针,当调用失败时返回-1。

当调用gethostbyname时,你不能使用perror()函数来输出错误信息,而应该使用herror()函数来输出。

无连接的客户/服务器程序,在原理上和连接的客户/服务器是一样的,两者的区别在于无连接的客户/服务器中的客户一般不需要建立连接,而且在发送接收数据时,需要指定远端机的地址。

阻塞和非阻塞阻塞函数在完成其指定的任务以前不允许程序调用另一个函数。

例如,程序执行一个读数据的函数调用时,在此函数完成读操作以前将不会执行下一程序语句。

当服务器运行到accept语句时,而没有客户连接服务请求到来,服务器就会停止在accept语句上等待连接服务请求的到来。

这种情况称为阻塞(blocking)。

而非阻塞操作则可以立即完成。

比如,如果你希望服务器仅仅注意检查是否有客户在等待连接,有就接受连接,否则就继续做其他事情,则可以通过将Socket设置为非阻塞方式来实现。

非阻塞socket在没有客户在等待时就使accept调用立即返回。

#include <unistd.h>#include <fcntl.h>……sockfd = socket(AF_INET,SOCK_STREAM,0);fcntl(sockfd,F_SETFL,O_NONBLOCK);……通过设置Socket为非阻塞方式,可以实现"轮询"若干Socket。

当企图从一个没有数据等待处理的非阻塞Socket读入数据时,函数将立即返回,返回值为-1,并置errno值为EWOULDBLOCK。

但是这种"轮询"会使CPU处于忙等待方式,从而降低性能,浪费系统资源。

而调用select()会有效地解决这个问题,它允许你把进程本身挂起来,而同时使系统内核监听所要求的一组文件描述符的任何活动,只要确认在任何被监控的文件描述符上出现活动,select()调用将返回指示该文件描述符已准备好的信息,从而实现了为进程选出随机的变化,而不必由进程本身对输入进行测试而浪费CPU开销。

select函数原型为:int select(intnumfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, structtimeval*timeout);其中readfds、writefds、exceptfds分别是被select()监视的读、写和异常处理的文件描述符集合。

相关文档
最新文档