套接字(socket)编程简单实现server-client聊天程序
来源:互联网 发布:少儿英语软件推荐 编辑:程序博客网 时间:2024/05/22 12:24
1、socket
在TCP/IP协议中,一个IP地址标识网络通讯中唯一一台主机,而一个IP地址+一个TCP(或UDP)端口号就可以标识网络通讯中的一个进程,此时的IP地址+端口号即称为socket。
内存中的多字节数据相对于内存地址有大小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大小端之分,网络数据流同样也有大小端之分:先发出的数据是低地址,后发出的数据是搞地质,TCP/IP协议规定网络数据流采用大端字节序,即低地址高字节。
1)计算机分为大端机和小端机,那么如何使同样的C代码在大端机和小端机上都能正常运行呢?库函数一节为我们提供了转换的接口:
include<arpa/inet.h>unit32_t htonl(unit32_t hostlong);//32位的长整数从主机字节序转换为网络字节序unit16_t htons(unit16_t hostshort);//16位的短整数从主机字节序转换为网络字节序unit32_t ntohl(unit32_t netlong);//32位的长整数从网络字节序转换为主机字节序unit16_t ntohs(unit16_t netshort);//16位的短整数从网络字节序转换为主机字节序
2)由于网络传输是二进制比特流传输,所以必须将我们常用的十进制的IP地址与网络字节序的二进制形式的IP源码互相转换才可以将数据传输到准确的地址,下面是地址转换函数介绍:
int inet_aton(const char* cp, struct in_addr *inp);//将字符串cp的十进制转换为网络字节序的二进制形式后存储到inp中char* inet_ntoa(struct in_addr *in);//将网络字节序的二进制形式转换为十进制的字符串形式,返回字符串的首地址
2、socket地址的数据类型及相关函数
1)结构体
IPV4套接字地址结构体:
struct sockaddr_in{unit8_t sin_len;sa_famliy_t sin_famliy;//协议家族in_port_t sin_port;//端口号struct in_addr sin_addr;//IP地址char sin_zero[8];};
通用套接字地址结构体:
struct sockaddr{unit8_t sa_len;sa_famliy sa_famlity;char sa_data[14];};
2)相关函数
socket:
bind:
listen:
accept与connect:
send和recv:
close:
3、下面通过简单的客户端/服务器程序实例来学习socket API。
server端即服务器端:服务器由于不知道客户何时回请求建立连接,所以必须绑定端口之后进行监听;
client端即客户端:只需向服务器端发送连接请求(connect);
客户端主动发起请求连接,服务器接受连接请求,完成“三次握手”;服务器与客户端都可以发起断开连接请求,完成”四次挥手“的过程。
基本框架图(此图为摘录):
代码如下:
server.c:
#include<stdio.h>#include<stdlib.h>#include<sys/socket.h>#include<netinet/in.h>#include<unistd.h>#include<string.h>#include<sys/types.h>#define _PORT_ 9999#define _BACKLOG_ 10int main(){ int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock < 0){ perror("socket"); exit(1); } int opt = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); struct sockaddr_in server_socket; struct sockaddr_in client_socket; bzero(&server_socket, sizeof(server_socket)); server_socket.sin_family = AF_INET; server_socket.sin_addr.s_addr = htonl(INADDR_ANY); server_socket.sin_port = htons(_PORT_); if(bind(sock, (struct sockaddr*)&server_socket, sizeof(struct sockaddr_in)) < 0) { perror("bind"); close(sock); exit(2); } if(listen(sock, _BACKLOG_) < 0) { perror("listen"); close(sock); exit(3); } printf("bind and listen success, wait accept..\n"); while(1) { socklen_t len = 0; int client_sock = accept(sock, (struct sockaddr*)&client_socket, &len); if(client_sock < 0) { perror("accept"); close(sock); exit(4); } char buf_ip[INET_ADDRSTRLEN]; memset(buf_ip, '\0', sizeof(buf_ip)); inet_ntop(AF_INET,&client_socket.sin_addr, buf_ip, sizeof(buf_ip)); printf("get connect, ip is : %s port is : %d\n",buf_ip, ntohs(client_socket.sin_port)); while(1) { char buf[1024]; memset(buf, '\0',sizeof(buf)); read(client_sock, buf, sizeof(buf)); printf("client#:%s\n",buf); printf("server#:"); memset(buf, '\0', sizeof(buf)); fgets(buf, sizeof(buf), stdin); buf[strlen(buf)-1] = '\0'; write(client_sock, buf, strlen(buf)+1); printf("please wait...\n"); } } close(sock); return 0;}
client.c:
#include<stdio.h> #include<unistd.h>#include<sys/socket.h>#include<sys/types.h>#include<string.h>#include<netinet/in.h>#include<arpa/inet.h>#define SERVER_PORT 9999#define SERVER_IP "192.168.43.121"int main(int argc, char *argv[]){ if(argc != 2) { printf("Usage: client IP \n"); return 1; } char *str = argv[1]; char buf[1024]; memset(buf, '\0', sizeof(buf)); struct sockaddr_in server_sock; int sock = socket(AF_INET, SOCK_STREAM, 0); bzero(&server_sock, sizeof(server_sock)); server_sock.sin_family = AF_INET; inet_pton(AF_INET, SERVER_IP, &server_sock.sin_addr); server_sock.sin_port = htons(SERVER_PORT); int ret = connect(sock, (struct sockaddr*)&server_sock, sizeof(server_sock)); if(ret < 0) { printf("perror"); return 1; } printf("connect success....\n"); while(1) { printf("client#:"); fgets(buf, sizeof(buf), stdin); buf[strlen(buf)-1] = '\0'; write(sock, buf, sizeof(buf)); if(strncasecmp(buf, "quit", 4) == 0) { perror("perror"); break; } printf("please wait...\n"); read(sock, buf, sizeof(buf)); printf("server$: %s\n",buf); } close(sock); return 0;}
4、测试结果
打开一个terminal运行服务器端server,再打开另外一个terminal运行客户端client,并加上通过ifconfig查出的IP地址即可实现服务器端与客户端的连接。
- 套接字(socket)编程简单实现server-client聊天程序
- client.c和server.c 网络套接字socket编程热身程序
- 网络套接字socket(tcp、server、client)
- Socket聊天程序(Client)
- 基于Linux的SOCKET编程之TCP半双工Client-Server聊天程序
- 基于Linux的Socket编程之TCP全双工Server-Client聊天程序
- 基于Linux的SOCKET编程之TCP半双工Client-Server聊天程序
- 基于Linux的Socket编程之TCP全双工Server-Client聊天程序
- Socket通讯编程实现简单的任意聊天程序
- c#基于socket编程实现简单多人聊天程序
- 一个java网络编程Socket的例子,实现Server与Client聊天
- Java Socket 简单的Client/Server程序
- Java Socket 简单的Client/Server程序
- Java Socket 简单的Client/Server程序
- C++套接字编程(聊天程序)
- TCP套接字(server/client实现)
- 【Little_things】事件驱动的带界面的Client/Server聊天小程序(java socket)
- Java: 写个简单的Client,Server聊天程序
- VS2017添加引用失败
- tomcat memcached session共享
- hdu 2579 余数判重
- Java基础加强总结——注解(Annotation)
- Mike and Cellphone
- 套接字(socket)编程简单实现server-client聊天程序
- proc_create的使用方法
- RGB 格式备忘
- 我就是你们口中的程序员,爱信不信
- java程序员的python之路(面向对象)
- Java
- 年轻人应该如何看待高薪
- ML--Apriori关联分析
- Scrapy-settings源码分析