概述
进程间的通讯依赖于Linux内核,缺陷:无法多机通讯
Linux网络编程:
地址:IP地址、端口号;
数据:协议(数据格式):http、TCP/UDP客户端:ftp、http、socket
socket套接字 :TCP:面向连接(可靠);UDP:面向报文(不太可靠),数据量大,如视频
TCP/UDP的对比:
端口号的作用:
一台拥有IP地址的主机可以提供许多服务,比如web服务、FTP服务、SMTP服务等
这些服务完全可以通过一个IP来实现。主机是怎样区分不同的网络服务的?显然不能只靠IP地址,因为IP地址与网络服务的关系是一对多的关系。
实际上是通过IP地址加端口号来区分不同的服务的
端口通过了一种访问通道
服务器一般都是通过知名端口号来识别的。例如对于某个TCP/IP来说,FTP服务器的TCP端口号都是21,每个Telnet服务器的端口号都是23,每个TFTP(简单文件传输协议)服务器的UDP端口号都是69。
字节序:
字节序是指多字节数据在计算机内存中储存或者网络传输时各字节的储存顺序。
常见序:
Little endian 小端字节序:将低字节储存在起始地址
Big endian 大端字节序:将高字节储存在起始地址
网络字节序 = 大端字节序
字节序转换API
#include <arpa/inet.h>
uint16_t htons(uint16_t host16bitvalue);//返回网络字节序的值
uint32_t htonl(uint32_t host32bitvalue);//返回网络字节序的值
uint16_t ntohs(uint16_t net16bitvalue);//返回主机字节序的值
uint32_t ntohl(uint32_t net32bitvable);//返回主机字节序的值
h代表host,n代表net,s代表short(两个字节),l代表long(4个字节),通过上面的四个函数可以实现主机字节序和网络字节序之间的转换。有时可以用INASDDR_ANY,INADDR_ANY指定地址操作系统自己获取。
socket编程(服务器)
socket核心函数
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
int socket(int domain,int type,int protocl);
int bind(int sockfd,const struct sockaddr*my_addr,socklen_t addrlen);
int listen(int sockfd,int backlog);
int accept(int sockfd,struct sockaddr*addr,socklen_t*addlen);
int connect(int sockfd,const struct sockaddr*serv_addr,socklen_t addrlen);
int close(int fd);
1.指定连接协议(socket();)
2.地址准备好(bind();)
地址API转换
3.监听(listen();)
4.连接(accept();)
数据收发常用的第二套API
客户端的connect函数
服务端、客户端代码
服务端框架
telnet+IP+端口号进行连接
server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main()
{
int s_fd;
int n_read;
char readBuf[128];
char *msg = "I get your connect!";
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
//1.int socket(int domain, int type, int protocol);
//创建一个socket
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("scoket");
exit(-1);
}
//设置socket地址
s_addr.sin_family = AF_INET; //地址族:使用IPv4
s_addr.sin_port = htons(8989); //端口号,使用网络字节序表示
inet_aton("192.168.66.66",&s_addr.sin_addr); //IP地址v4地址,用网络字节序表示
/*struct sockaddr_in
{
sa_family_t sin_family; //地址族:AF_INET
u_int16_t sin_port; //端口号,要使用网络字节序表示
struct in_addr sin_addr; //IPv4地址结构体
char sin_zero[8]; //不使用
}
struct in_addr
{
u_int32_t s_addr; //IPv4地址,要用网络字节序表示
}*/
//分配地址信息,socket命名
//2.int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
//创建一个监听队列
//3.int listen(int sockfd, int backlog);
listen(s_fd,10);
//连接
//4.int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int clen = sizeof(struct sockaddr_in); //大小
int c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen); //强制转换,不然会有警告
if(c_fd == -1){
perror("accept");
}
printf("get connect:%sn",inet_ntoa(c_addr.sin_addr));
//读取
//5.read
n_read = read(c_fd,readBuf,128);
if(n_read == -1){
perror("read");
}else{
printf("get message:%d,%sn",n_read,readBuf);
}
//写入
//6.write
write(c_fd,msg,strlen(msg));
//7.close
close(s_fd); //关闭
close(c_fd);
return 0;
}
客户端框架
client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main()
{
int c_fd;
int n_read;
char readBuf[128];
char *msg = "msg from client!";
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
//1.int socket(int domain, int type, int protocol);
c_fd = socket(AF_INET,SOCK_STREAM,0);
if(c_fd == -1){
perror("scoket");
exit(-1);
}
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(8989);
inet_aton("192.168.31.41",&c_addr.sin_addr);
/*struct sockaddr_in
{
sa_family_t sin_family; //地址族:AF_INET
u_int16_t sin_port; //端口号,要使用网络字节序表示
struct in_addr sin_addr; //IPv4地址结构体
char sin_zero[8]; //不使用
}
struct in_addr
{
u_int32_t s_addr; //IPv4地址,要用网络字节序表示
}*/
//客户端不需要绑定和监听,直接连接服务器
//2. int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){ //连接
perror("connect");
exit(-1);
}
//3.send
write(c_fd,msg,strlen(msg));
//4.read
n_read = read(c_fd,readBuf,128);
if(n_read == -1){
perror("read");
}else{
printf("get message from client : %d,%sn",n_read,readBuf);
}
//5.close
//关闭连接
close(c_fd);
return 0;
}
实现双方聊天
TCP服务端
server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main(int argc,char **argv) //传参 ./server IP 端口号
{
int s_fd;
int c_fd;
int n_read;
char readBuf[128] = {0};
//char *msg = "I get your connect!";
char msg[128] = {0};
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
if(argc != 3){
printf("param is not goodn");
exit(-1);
}
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
//1.int socket(int domain, int type, int protocol);
//创建一个socket
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("scoket");
exit(-1);
}
//设置socket地址
s_addr.sin_family = AF_INET; //地址族:使用IPv4
s_addr.sin_port = htons(atoi(argv[2])); //端口号,使用网络字节序表示,atoi()将ASCII强制转换为int
inet_aton(argv[1],&s_addr.sin_addr); //IP地址v4地址,用网络字节序表示
/*struct sockaddr_in
{
sa_family_t sin_family; //地址族:AF_INET
u_int16_t sin_port; //端口号,要使用网络字节序表示
struct in_addr sin_addr; //IPv4地址结构体
char sin_zero[8]; //不使用
}
struct in_addr
{
u_int32_t s_addr; //IPv4地址,要用网络字节序表示
}*/
//分配地址信息,socket命名
//2.int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
//创建一个监听队列
//3.int listen(int sockfd, int backlog);
listen(s_fd,10);
//连接
//4.int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int clen = sizeof(struct sockaddr_in);
while(1){ //不断的读取和写入
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen); //连接
if(c_fd == -1){
perror("accept");
exit(-1); //连接失败退出
}
printf("get connect:%sn",inet_ntoa(c_addr.sin_addr));
if(fork() == 0){ //创建子进程,实现同时运行两个while(1)
//6.write
while(1){
memset(msg,0,sizeof(msg)); //清除原始数据
printf("input: n");
gets(msg); //没输入时阻塞
write(c_fd,msg,strlen(msg)); //将输入信息存入msg进行交互
}
}
//5.read
while(1){
memset(readBuf,0,sizeof(readBuf)); //清楚原始数据
//ssize_t read(int fd, void *buf, size_t count);
n_read = read(c_fd,readBuf,128); //读取
if(n_read == -1){
perror("read");
}else{
printf("get message:%d,from client:%sn",n_read,readBuf);
}
}
//7.close
close(s_fd);
close(c_fd);
}
return 0;
}
TCP客户端
client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main(int argc,char **argv)
{
int c_fd;
int n_read;
char readBuf[128];
//char *msg = "msg from client!";
char msg[128] = {0};
struct sockaddr_in c_addr;
if(argc != 3){
printf("param is not goodn");
exit(-1);
}
memset(&c_addr,0,sizeof(struct sockaddr_in));
//1.int socket(int domain, int type, int protocol);
c_fd = socket(AF_INET,SOCK_STREAM,0);
if(c_fd == -1){
perror("scoket");
exit(-1);
}
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
/*struct sockaddr_in
{
sa_family_t sin_family; //地址族:AF_INET
u_int16_t sin_port; //端口号,要使用网络字节序表示
struct in_addr sin_addr; //IPv4地址结构体
char sin_zero[8]; //不使用
}
struct in_addr
{
u_int32_t s_addr; //IPv4地址,要用网络字节序表示
}*/
//2. int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){
perror("connect");
exit(-1);
}
while(1){ //不断进行读写操作
if(fork() == 0){ //创建子进程
//3.send
while(1){
memset(msg,0,sizeof(msg));
printf("input: n");
gets(msg);
write(c_fd,msg,strlen(msg));
}
}
while(1){
//4.read
memset(readBuf,0,sizeof(readBuf));
n_read = read(c_fd,readBuf,128);
if(n_read == -1){
perror("read");
}else{
printf("get message from client : %d,%sn",n_read,readBuf);
}
}
}
//5.close
close(c_fd);
return 0;
}
多方消息收发 ,TCP服务端
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main(int argc,char **argv)
{
int s_fd;
int c_fd;
int n_read;
int mark = 0;
char readBuf[128] = {0};
//char *msg = "I get your connect!";
char msg[128] = {0};
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
if(argc != 3){
printf("param is not goodn");
exit(-1);
}
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
//1.int socket(int domain, int type, int protocol);
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("scoket");
exit(-1);
}
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&s_addr.sin_addr);
/*struct sockaddr_in
{
sa_family_t sin_family; //地址族:AF_INET
u_int16_t sin_port; //端口号,要使用网络字节序表示
struct in_addr sin_addr; //IPv4地址结构体
char sin_zero[8]; //不使用
}
struct in_addr
{
u_int32_t s_addr; //IPv4地址,要用网络字节序表示
}*/
//2.int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
//3.int listen(int sockfd, int backlog);
listen(s_fd,10);
//4.int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int clen = sizeof(struct sockaddr_in);
while(1){
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);
if(c_fd == -1){
perror("accept");
}
mark++;
printf("get connect:%sn",inet_ntoa(c_addr.sin_addr));
if(fork() == 0){
if(fork() == 0){
//6.write
while(1){
sprintf(msg,"welcom No.%d client",mark);
write(c_fd,msg,strlen(msg));
sleep(3);
}
}
//5.read
while(1){
memset(readBuf,0,sizeof(readBuf));
n_read = read(c_fd,readBuf,128);
if(n_read == -1){
perror("read");
}else{
printf("get message:%d,from client:%sn",n_read,readBuf);
}
}
//7.close
close(s_fd);
close(c_fd);
break;
}
}
return 0;
}
最后
以上就是紧张皮卡丘为你收集整理的LINUX系统编程__网络编程socket编程(服务器)客户端的connect函数服务端、客户端代码实现双方聊天的全部内容,希望文章能够帮你解决LINUX系统编程__网络编程socket编程(服务器)客户端的connect函数服务端、客户端代码实现双方聊天所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复