socket即ip+port,当然这是最直接的理解,网络的通信都离不开使用到socket,下面的聊天程序是基于tcp的简单通信过程,服务器端创建两个socket描述符,一个用于在服务器端监听,另一个用来接收客户端连接的请求。客户端使用connect函数向服务器发出连接请求,这里面包含了tcp的三次握手过程,连接完成之后就是cs间的相互通信了。
/****************************************************/
/* server.c */
/* @2013-03-23 */
/****************************************************/
#include<sys/socket.h>//提供socket函数及数据结构
#include<sys/types.h>//数据类型定义
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<netinet/in.h>//定义数据结构sockaddr_in
#include<arpa/inet.h>//提供ip地址转换函数
#define BUFSIZE 100
int srv_sockfd,client_sockfd;//套接字描述符
char recvBuf[BUFSIZE],sendBuf[BUFSIZE];
struct sockaddr_in srv_addr;//服务器套接字地址
struct sockaddr_in client_addr;
//创建tcp套接字
int tcpServer()
{
memset(&srv_addr,0,sizeof(srv_addr));
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.s_addr = INADDR_ANY;
srv_addr.sin_port = htons(8889);
if((srv_sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket creation failed");
return 1;
}
//设置套接字选项,避免地址使用错误
int on=1;
if((setsockopt(srv_sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int))) < 0)
{
perror("setsockopt failed");
return 1;
}
//绑定套接字到服务器的网络地址上
if((bind(srv_sockfd,(struct sockaddr *)&srv_addr,sizeof(struct sockaddr))) <0)
{
perror("bind failed");
return 1;
}
//建立监听队列
listen(srv_sockfd,5);
//等待客户端链接请求
int sin_size=sizeof(struct sockaddr_in);
client_sockfd = accept(srv_sockfd,(struct sockaddr *)&client_addr,(socklen_t *)&sin_size);
if(client_sockfd < 0)
{
perror("accept failed");
return 1;
}
return client_sockfd;
}
//通讯过程
int communicate(int sockfd)
{
while(1)
{
if(( recv(sockfd,recvBuf,BUFSIZE,0)) < 0)
{
perror("recv failed");
return 1;
}
if(recvBuf[0] == 'q'&& recvBuf[1] == '\0')//保证只是输入q时候才结束聊天
{
send(sockfd,"q",strlen("q")+1,0);
printf("Chat end!\n");
break;
}
printf("%s : %s\n",inet_ntoa(client_addr.sin_addr),recvBuf);
//发送数据给客户端
printf("I :");
scanf("%s",sendBuf);
if((send(sockfd,sendBuf,BUFSIZE,0)) < 0)
{
perror("send failed");
return 1;
}
}
return 0;
}
int main()
{
printf("Waiting for connection...\n");
int clientfd= tcpServer();
if(clientfd != 1)
{
printf("welcome %s to connect\n",inet_ntoa(srv_addr.sin_addr));
communicate(clientfd);
close(client_sockfd);
close(srv_sockfd);
}
return 0;
}
/****************************************************/
/* client.c */
/* @2013-03-23 */
/****************************************************/
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#define BUFSIZE 100
char sendBuf[BUFSIZE];
char recvBuf[BUFSIZE];
struct sockaddr_in srv_addr;//服务器端网络地址
int client_sockfd;//客户端套接字描述符
int re;
//创建tcp套接字并连接服务器
int tcpClient()
{
client_sockfd = socket(AF_INET,SOCK_STREAM,0);
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
srv_addr.sin_port = htons(8889);
int len = sizeof(srv_addr);
//与服务器链接
if(( re = connect(client_sockfd,(struct sockaddr *)&srv_addr,len)) < 0)
{
perror("connect failed");
return 1;
}
return client_sockfd;
}
//开始通讯
int communicate(int sockfd)
{
while(1)
{
printf("I :");
scanf("%s",sendBuf);
if((send(client_sockfd,sendBuf,BUFSIZE,0)) < 0)
{
perror("send failed");
return 1;
}
//等待接收数据
if((recv(client_sockfd,recvBuf,BUFSIZE,0)) < 0)
{
perror("recv failed");
return 1;
}
if(recvBuf[0] == 'q'&& recvBuf[1] == '\0')//保证只是输入q的时候才结束聊天
{
send(client_sockfd,"q",strlen("q")+1,0);
printf("Chat end!\n");
break;
}
printf("%s : %s\n",inet_ntoa(srv_addr.sin_addr),recvBuf);
}
}
int main()
{
int clientfd = tcpClient();
if(clientfd != 1)
{
printf("success connect to %s...\n",inet_ntoa(srv_addr.sin_addr));
communicate(clientfd);
close(client_sockfd);
}
return 0;
}