socket

来源:互联网 发布:unity3d lerp函数 编辑:程序博客网 时间:2024/05/17 06:26

利用socket套接字聊天


套接字地址结构体

struct sockaddr_in{unsigned short sin_family;unsigned short sin_port;//端口struct in_addr sin_addr;//ipunsigned char  sin_zero[8];};


另外一个通用的结构
struct sockaddr{    unsigned short sa_family;    char           sa_data[14];};



//存放ip的结构体
struct in_addr{    unsigned int a_addr;};//将ip放在一个结构体中,是套接字接口早期不幸的产物



以上结构体都在netinet/in.h
无论何时我们都可以将sockaddr_in强制转换为sockaddr

typedef struct sockaddr SA;#include<sys/types.h>#include<sys/socket.h>int socket(int domain,int type,int protocol);int connect(int sockfd,struct sockaddr *serv_addr,int addrlen);int bind(int sockfd,struct sockaddr *my_addr,int addrlen);int listen(int sockfd,int backlog);int accept(int listenfd,struct sockaddr *addr,int *addrlen);





我们发现将socket和connect封装成一个open_clientfd函数是很方便的,客户端可以用它来和服务器建立连接

同样,将socket、bind、listen函数结合成一个open_listenfd的函数,服务端可以创建一个监听描述符。
--->
我将if((clientfd=socket(AF_INET,SOCK_STREAM,0))<0)写成了if(clientfd=socket(AF_INET,SOCK_STREAM,0)<0)导致了严重的错误
注意端口号是否被占用
<---

------------分割------------open.h

#include <stdio.h>#include <string.h>#include <arpa/inet.h>//use inet_aton();#include <netinet/in.h>//use htons();#include <sys/types.h>#include <sys/socket.h>//use socket() connect()typedef struct sockaddr SA;int open_clientfd(char *ip,int port){int clientfd;struct sockaddr_in serveraddr;bzero((char *)&serveraddr,sizeof(serveraddr));//设为0if((clientfd=socket(AF_INET,SOCK_STREAM,0))<0)return -1;inet_aton(ip,&serveraddr.sin_addr);//ipserveraddr.sin_port=htons(port);//portserveraddr.sin_family=AF_INET;//familyif(connect(clientfd,(SA*)&serveraddr,sizeof(serveraddr))<0)return -2;return clientfd;}int open_listenfd(int port){int listenfd;struct sockaddr_in serveraddr;bzero((char *)&serveraddr,sizeof(serveraddr));if((listenfd=socket(AF_INET,SOCK_STREAM,0))<0)return -1;serveraddr.sin_family=AF_INET;serveraddr.sin_addr.s_addr=INADDR_ANY;serveraddr.sin_port=htons(port);if(bind(listenfd,(SA*)&serveraddr,sizeof(serveraddr))<0) return -2;//bind(listenfd,(SA*)&serveraddr,sizeof(serveraddr));printf("%d\n",listenfd);if(listen(listenfd,1024)<0)return -3;return listenfd;}


---------------------------------open.h



第一版:客服端一直发送,服务端显示
 
   客服端----------------------------------echoclient.c#include <stdio.h>#include <unistd.h>#include <string.h>#include "open.h"#define max_long 1000int main(){int clientfd;clientfd=open_clientfd("127.0.0.1",1111);printf("%d\n",clientfd);while(1){char buf[max_long];bzero(&buf,max_long);fgets(buf,max_long,stdin);send(clientfd,buf,strlen(buf)-1,0);}close(clientfd);return 0;}----------------------------------echoclient.c  服务端----------------------------------echoserver.c#include <stdio.h>#include <unistd.h>#include "open.h"#include <string.h>#define max_long 1000void echo(int connfd);int main(){int listenfd;listenfd=open_listenfd(1111);printf("%d\n",listenfd );int connfd,addrlen;struct sockaddr_in clientaddr;while(1){addrlen=sizeof(clientaddr);connfd=accept(listenfd,(SA *)&clientaddr,&addrlen);echo(connfd);close(connfd);}return 0;}void echo(int connfd){while(1){char buf[max_long];bzero(&buf,max_long);recv(connfd,buf,max_long,0);printf("%s\n",buf);}}

第二版 :可以通过进程的创建,一个用来接受,一个用来发送
但是存在两个问题:
1 当直接杀死某一端的时候,另一端会一直循环输出

2 没有妥善的出来子父进程之间的关系

  客服端----------------------------------echoclient.c#include <stdio.h>#include <unistd.h>#include <string.h>#include "open.h"#define max_long 1000int main(){int clientfd;char *ip="127.0.0.1";clientfd=open_clientfd(ip,1111);//printf("%d\n",clientfd);if(clientfd>=0)printf("已经连接上%s\n",ip);pid_t pid;pid=fork();if(pid==0)//接受{while(1){char buf[max_long];bzero(&buf,max_long);int n=recv(clientfd,buf,max_long,0);if(buf[0]=='q')break;printf("%s\n",buf);}}else//发送{while(1){char buf[max_long];bzero(&buf,max_long);fgets(buf,max_long,stdin);send(clientfd,buf,strlen(buf)-1,0);}}close(clientfd);return 0;}----------------------------------echoclient.c  服务端----------------------------------echoserver.c#include <stdio.h>#include <unistd.h>#include "open.h"#include <string.h>#define max_long 1000void echo(int connfd);int main(){int listenfd;listenfd=open_listenfd(1111);//printf("%d\n",listenfd );int connfd,addrlen;struct sockaddr_in clientaddr;while(1){printf("等待别人连接:\n");addrlen=sizeof(clientaddr);connfd=accept(listenfd,(SA *)&clientaddr,&addrlen);printf("%s已连接\n",inet_ntoa(clientaddr.sin_addr));int pid;pid=fork();if(pid==0)//发送{while(1){char buf[max_long];bzero(&buf,max_long);fgets(buf,max_long,stdin);send(connfd,buf,strlen(buf)-1,0);}}else//接受{echo(connfd);}close(connfd);}return 0;}void echo(int connfd){while(1){char buf[max_long];bzero(&buf,max_long);int n=recv(connfd,buf,max_long,0);if(buf[0]=='q'){break;}printf("%s\n",buf);}}


这里是web服务器第一版

    通过1118端口,简单的响应浏览器的访问

#include <stdio.h>#include <unistd.h>#include "open.h"#include <string.h>#define max_long 10000typedef struct sockaddr SA;int main(){int listenfd;listenfd=open_listenfd(1118);if(listenfd<0)return -1;int connfd,addrlen;struct sockaddr_in clientaddr;while(1){printf("waite connect...\n");addrlen=sizeof(clientaddr);connfd=accept(listenfd,(SA *)&clientaddr,&addrlen);printf("connect success\n");FILE *client=fdopen(connfd,"w");char buf[max_long];//发送给浏览器阅读的头信息fprintf(client,"HTTP/1.1 200 OK\r\nServer:Testhttp server\r\nContent-length:1000\r\nContent-type:text/html\r\n\r\n");//需要显示的内容fprintf(client,"<html><title>test</title><body><p>this is a p<a href="">99999</a></p></body></html>");//sleep(10);fclose(client);}return 0;}



1 0
原创粉丝点击