Linux下Scoket聊天程序

在Linux下写了个client、server的聊天小程序。

下面介绍一下用到的几个函数

Client和Server都要用到的

创建socket
int scoket(int domain, int type, int protocol)
domain:说明主机采用的通讯协议簇,AF_INTR针对Internet。
type:所采用的的通信协议SOCK_STREAM为TCP,SOCK_DGRAM为UDP。
protocol:由于type制定了通讯协议,这里一般用0。
成功时返回文件描述符,失败返回-1并置errno。


发送函数

ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags);
sockfd:指定发送端套接字描述符。
buff:存放要发送数据的缓冲区
nbytes:实际要改善的数据的字节数
flags:一般设置为0
成功时返回发送的字节数。


接收函数

ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags);
sockfd:接收端套接字描述符
buff:用来存放recv函数接收到的数据的缓冲区
nbytes:指明buff的长度
flags:一般置为0


关闭函数

int close(int sockfd)


Server端用到的
绑定socket
bind
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
sockfd:函数socket的返回的文件描述符
addrlen:sockaddr结构体所占空间大小
my_addr:指向sockaddr的指针。
为了兼容,常用sockaddr_in代替sockaddr
struct sockaddr_in{
unsigned shor sin_family;
unsigned shot int sin_port;
struct in_addr sin_addr;
unsigned sin_zero[8];
}
sin_family为通信协议簇,我们一般用Internet,置为AF_INET。
sin_port为监听的端口号。
sin_addr一般设为INADDR_ANY,表示可以和任意主机通信。
sin_zero[8]用来填充。
bind用来将本地端口和sockfd返回的文件描述符绑定,成功返回0。失败返回-1并置errno。

创建监听
int listen(int sockfd, int backlog)
sockfd:是bind后的文件描述符。
backlog:请求排队的最大长度。当有多个client和服务器连接时,需要排队。
listen函数将bind的文件描述符变为监听套接字。成功返回0,失败返回-1并置errno。

接收连接
int accept(int sockfd, struct sockaddr *addr, int *addrlen)
sockfd:listen后的文件描述符。
addr和addrlen是客户端程序填写的。accept调用时,进程会一直阻塞直到客户端有程序来连接。
accept成功后,返回文件描述符,这个文件描述符用来跟client通信。

Client端用到的
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
sockfd:socket返回的文件描述符
serv_addr:储存了服务器端的连接信息,sin_add是服务器的地址,sin_port是服务器监听的端口
成功时返回0,sockfd是用来和服务器通信的文件描述符


client代码

socket->connect

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#define BUFSIZE 1024
#define SERVERPORT 12345
 
 
 int main(int argc,char *argv[])
 {
     int sockfd;//socket
     char sendBuf[BUFSIZE],recvBuf[BUFSIZE];
     int sendSize,recvSize;//用于记录记录发送和接收到数据的大小
     
     struct sockaddr_in servAddr;
	 char serverIP[16];//服务器IP
	 
	 int pid;
 
     if(argc !=2 )
     {
         perror("use: ./client [ServerIP]");
         exit(-1);
     }
	 strcpy(serverIP,argv[1]);
	 printf("server IP is: %s\n",serverIP);
  
     if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)//TCP
     {
     	perror("fail to establish a socket");
     	exit(-1);
     }
     printf("Success to establish a socket...\n");
     
     /*init sockaddr_in*/
	 bzero(&servAddr, sizeof(servAddr));//置零
 
     servAddr.sin_family=AF_INET;
     servAddr.sin_port=htons(SERVERPORT);//端口
    inet_pton(AF_INET,serverIP,&servAddr.sin_addr);//字符串转换为网络地址
     
     /*connect the socket*/
     if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-1)
     {
     	perror("fail to connect the socket");
     	exit(-1);
     }
     printf("Success to connect the socket...\n");
	 
	 if((pid=fork())<0)
	 {
		perror("fork error");
		exit(-1);
	 }
	 
	 if(pid==0){//子进程
		while(1){//读输入,发送
			fgets(sendBuf,BUFSIZE,stdin);//
			send(sockfd,sendBuf,strlen(sendBuf),0);
			memset(sendBuf,0,sizeof(sendBuf));
		}
	 
	 }
	 else if(pid>0){//父进程
		while(1){//接受数据,显示
			if(recv(sockfd,recvBuf,BUFSIZE,0)==-1){
				perror("fail to receive data");
				close(sockfd);
				exit(-1);
			}
			printf("Server:%s\n",recvBuf);
			memset(recvBuf,0,sizeof(recvBuf));
		}
	}
	 
      
     return 0;
 }

server代码

scoket-->bind-->listen-->accept

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>


#define SERVERPORT 12345
#define BACKLOG 5
#define MAX_CON_NO 10
#define BUFSIZE 1024

int main(int argc,char *argv[])
{
    struct sockaddr_in serverSockaddr,clientSockaddr;
    char sendBuf[BUFSIZE],recvBuf[BUFSIZE];
    int sendSize,recvSize;
    int sockfd,clientfd;
    int sinSize=0;
	int pid;

    /*establish a socket*/
    if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1)
    {
        perror("fail to establish a socket");
        exit(1);
    }
    printf("Success to establish a socket...\n");

    /*init sockaddr_in*/
    serverSockaddr.sin_family=AF_INET;
    serverSockaddr.sin_port=htons(SERVERPORT);
    serverSockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
    bzero(&(serverSockaddr.sin_zero),8);

    /*bind socket*/
    if(bind(sockfd,(struct sockaddr *)&serverSockaddr,sizeof(struct sockaddr))==-1)
    {
        perror("bind error");
        exit(1);
    }
    printf("Success to bind the socket...\n");

    /*listen on the socket*/
    if(listen(sockfd,BACKLOG)==-1)
    {
        perror("fail to listen");
        exit(1);
    }

    /*accept a client's request*/
    if((clientfd=accept(sockfd,(struct sockaddr  *)&clientSockaddr, &sinSize))==-1)
    {
        perror("fail to accept");
        exit(-1);
    }
    printf("Success to accpet a connection request...\n");
    printf("Client IP is %s\n",inet_ntoa(clientSockaddr.sin_addr));//client IP
	
	if((pid=fork())<0)
	 {
		perror("fork error\n");
		exit(-1);
	 }
	 
	 if(pid==0){//子进程
		while(1){//读输入,发送
			fgets(sendBuf,BUFSIZE,stdin);//
			send(clientfd,sendBuf,strlen(sendBuf),0);
			memset(sendBuf,0,sizeof(sendBuf));
		}
	 
	 }
	 else if(pid>0){//父进程
		while(1){//接受数据,显示
			if(recv(clientfd,recvBuf,BUFSIZE,0)==0){
				perror("fail to receive data");
				close(clientfd);
				exit(-1);
			}
			printf("Client:%s\n",recvBuf);
			memset(recvBuf,0,sizeof(recvBuf));
		}
	}
    
    return 0;
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值