进程间的通信有很多种方法,本地进程之间通过一个唯一标识的pid进行通信,网络之间的进程进行通信,也需要一个唯一的标志符。根据TCP/IP协议,网络层的ip地址可以唯一的标识网络中的一台主机,协议加端口号可以标识这台主机中的进程。ip地址,协议加端口就可以唯一标识网络中的进程,进程之间可以通过这个标识进行通信。
目前几乎所有网络进程都是采用socket进行通信。socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭),这些函数在很多文章里都有介绍,这里不再赘述。
socket通信中,一个进程需要被设置成服务器,另一个需要被设置成客户端。我们将第一个进程分别设置成服务器和客户端,另一个进程我们在电脑中安装网络调试助手,设置成对应的客户端和服务器,测试它们之间的通信情况。
设置成服务器的代码如下:
#define BUFF_LEN ( 512 )
static int socket_server_fd = 0;
{
print_ids("socket rcv thread:");
struct sockaddr_in socketaddr;
unsigned char buf[BUFF_LEN] = {0};
ssize_t recv_len;
int ret = -1;
while(1)
{
printf("thread step = %d \n",thread_step);
switch(thread_step)
{
case 0://socket
printf("socket case 0\n");
socket_server_fd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == socket_server_fd)
{
perror("socket\n");
sleep(1);
break;
}
printf("creat socket success\n");
thread_step = 1;
break;
printf("socket case 1\n");
memset(&socketaddr, 0, sizeof(socketaddr));
socketaddr.sin_family = AF_INET;
socketaddr.sin_port = htons(8080);
socketaddr.sin_addr.s_addr = htonl(INADDR_ANY);
{
sleep(1);
break;
}
thread_step = 2;
break;
printf("socket case 2\n");
ret = listen(socket_server_fd, 10);
printf("listen return value is %d\n",ret);
if(ret == -1)
{
sleep(1);
break;
}
else
{
thread_step = 3;
}
break;
case 3:
printf("socket case 3\n");
if((conn_fd = accept(socket_server_fd, (struct sockaddr*)NULL, NULL)) == -1)
{
printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
continue;
}
thread_step = 4;
break;
printf("socket case 4\n");
recv_len = recv(conn_fd, buf, sizeof(buf),0);
printf("rcv len = %d \n",recv_len);
buf[recv_len] = '\0';
if(recv_len)
{
printf("rcv info is = %s \n",buf);
memset(buf, 0, strlen(buf));
}
break;
break;
}
}
return ((void*)0);
}
设置成客户端的代码如下:
#define SERVER_ADDR ( "192.168.0.132" )
#define SERVER_IP ( 8080 )
static int socket_fd = 0;
void socket_client_mode(void)
{
print_ids("socket rcv thread:");
int ret = -1;
unsigned char buf[BUFF_LEN] = {0};
struct sockaddr_in socketaddr;
ssize_t recv_len;
printf("thread step = %d \n",thread_step);
switch(thread_step)
{
case 0://socket
printf("socket case 0\n");
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == socket_fd)
{
perror("socket\n");
sleep(1);
break;
}
printf("creat socket success\n");
thread_step = 1;
break;
printf("socket case 1\n");
memset(&socketaddr, 0, sizeof(socketaddr));
socketaddr.sin_family = AF_INET;
socketaddr.sin_port = htons(SERVER_IP);
socketaddr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
{
perror("connect \n");
//close(socket_fd);
sleep(1);
break;
}
thread_step = 2;
break;
case 2://revc
{
printf("socket case 2\n");
recv_len = recv(socket_fd, buf, sizeof(buf), 0);
printf("rcv len = %d\n",recv_len);
if(recv_len)
{
printf("rcv info is = %s \n",buf);
memset(buf, 0, strlen(buf));
}
}
break;
break;
}
}
return ((void*)0);
}
发送数据的代码如下:
static int socket_mode = 0;
static char socket_send[100] = {0};
{
int len = strlen(data);
strcpy(socket_send,data);
{
if(send(socket_fd, socket_send, strlen(socket_send), 0) < 0)
{
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
}
else if(thread_step == 4)
{
if(send(conn_fd, socket_send, strlen(socket_send), 0) < 0)
{
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
//exit(0);
}
}
else
{}
void test_send_data(void)
{
static int data = 0;
char string1[30];
while(1)
{
if(data<100)
{
data++;
}
sprintf(string1,"%d",data);
puts(string1);
char* str1 ="socket send data:";
char* str2 =(char *) malloc(strlen(str1) + strlen(string1)+1);
strcpy(str2, str1);
strcat(str2, string1);
socket_send_data(str2);
printf("send info is : %s\n",str2);
free(str2);
str2 = NULL;
sleep(1);
}
}
完整代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#define BUFF_LEN ( 512 )
#define SERVER_ADDR ( "192.168.0.132" )
#define SERVER_IP ( 8080 )
static int socket_fd = 0;
static int socket_server_fd = 0;
static int socket_mode = 0;
static int conn_fd = 0;
{
int len = strlen(data);
strcpy(socket_send,data);
{
if(send(socket_fd, socket_send, strlen(socket_send), 0) < 0)
{
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
}
else if(thread_step == 4)
{
if(send(conn_fd, socket_send, strlen(socket_send), 0) < 0)
{
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
//exit(0);
}
}
else
{}
{
static int data = 0;
char string1[30];
while(1)
{
if(data<100)
{
data++;
}
sprintf(string1,"%d",data);
puts(string1);
char* str1 ="socket send data:";
char* str2 =(char *) malloc(strlen(str1) + strlen(string1)+1);
strcpy(str2, str1);
strcat(str2, string1);
socket_send_data(str2);
printf("send info is : %s\n",str2);
free(str2);
str2 = NULL;
sleep(1);
}
}
{
print_ids("socket rcv thread:");
struct sockaddr_in socketaddr;
unsigned char buf[BUFF_LEN] = {0};
ssize_t recv_len;
int ret = -1;
while(1)
{
printf("thread step = %d \n",thread_step);
switch(thread_step)
{
case 0://socket
printf("socket case 0\n");
socket_server_fd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == socket_server_fd)
{
perror("socket\n");
sleep(1);
break;
}
printf("creat socket success\n");
thread_step = 1;
break;
printf("socket case 1\n");
memset(&socketaddr, 0, sizeof(socketaddr));
socketaddr.sin_family = AF_INET;
socketaddr.sin_port = htons(8080);
socketaddr.sin_addr.s_addr = htonl(INADDR_ANY);
{
sleep(1);
break;
}
thread_step = 2;
break;
printf("socket case 2\n");
ret = listen(socket_server_fd, 10);
printf("listen return value is %d\n",ret);
if(ret == -1)
{
sleep(1);
break;
}
else
{
thread_step = 3;
}
break;
case 3:
printf("socket case 3\n");
if((conn_fd = accept(socket_server_fd, (struct sockaddr*)NULL, NULL)) == -1)
{
printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
continue;
}
thread_step = 4;
break;
printf("socket case 4\n");
recv_len = recv(conn_fd, buf, sizeof(buf),0);
printf("rcv len = %d \n",recv_len);
buf[recv_len] = '\0';
if(recv_len)
{
printf("rcv info is = %s \n",buf);
memset(buf, 0, strlen(buf));
}
break;
break;
}
}
return ((void*)0);
}
{
print_ids("socket rcv thread:");
int ret = -1;
unsigned char buf[BUFF_LEN] = {0};
struct sockaddr_in socketaddr;
ssize_t recv_len;
printf("thread step = %d \n",thread_step);
switch(thread_step)
{
case 0://socket
printf("socket case 0\n");
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == socket_fd)
{
perror("socket\n");
sleep(1);
break;
}
printf("creat socket success\n");
thread_step = 1;
break;
printf("socket case 1\n");
memset(&socketaddr, 0, sizeof(socketaddr));
socketaddr.sin_family = AF_INET;
socketaddr.sin_port = htons(SERVER_IP);
socketaddr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
{
perror("connect \n");
//close(socket_fd);
sleep(1);
break;
}
thread_step = 2;
break;
case 2://revc
{
printf("socket case 2\n");
recv_len = recv(socket_fd, buf, sizeof(buf), 0);
printf("rcv len = %d\n",recv_len);
if(recv_len)
{
printf("rcv info is = %s \n",buf);
memset(buf, 0, strlen(buf));
}
}
break;
break;
}
}
return ((void*)0);
}
void* socket_thread_fun(void *arg)
{
if(socket_mode)
{
socket_client_mode();
}
else
{
socket_server_mode();
}
}
{
int ret = -1;
pthread_t send_thread;
pthread_t socket_thread;
pthread_create(&send_thread, NULL, send_thread_fun, NULL);
pthread_create(&socket_thread, NULL, socket_thread_fun, NULL);
pthread_join(send_thread,NULL);
pthread_join(socket_thread,NULL);
}