【无标题】

1.查看while源代码

系统调用

socket

函数原型

int socket(int domain, int type, int protocol);

参数说明:

domain:指定通信协议族。常用的协议族有AF_INET、AF_UNIX等,对于TCP协议,该字段应为AF_INET(ipv4)或AF_INET6(ipv6)。

type:指定socket类型。常用的socket类型有SOCK_STREAM、SOCK_DGRAM等。SOCK_STREAM针对于面向连接的TCP服务应用。SOCK_DGRAM对应于无连接的UDP服务应用。

protocol:指定socket所使用的协议,一般我们平常都指定为0,使用type中的默认协议。严格意义上,IPPROTO_TCP(值为6)代表TCP协议。

bind

函数原型

int bind(int sockfd,const struct sockaddr * addr,socklen_t addrlen);

bind()函数用于服务器端,服务器的网络地址和端口号通常固定不变,客户端得知服务器的地址和端口号以后,可以主动向服务器请求连接。因此服务器需要调用bind()绑定地址。bingd()函数定义在sys/socket.h头文件中;

sockfd表示socket文件的文件描述符,一般为socket函数的返回值;
 

listen

函数原型

int listen(int sockfd, int backlog);  

参数说明:
sockfd:套接字的文件描述符,即socket()系统调用返回的fd
backlog:保存客户端请求的队列长度

listen()系统调用是比较简单的,但是涉及了backlog,这个参数是比较复杂的,影响到半连接队列和全连接队列

accept

函数原型

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);  

sockfd:套接字的文件描述符,socket()系统调用返回的文件描述符fd

addr:指向存放地址信息的结构体的首地址

addrlen:存放地址信息的结构体的大小,其实也就是sizof(struct sockaddr)

可以看出,bind(),connect(),以及accept()的参数都是一致的。

connect

函数原型

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 

sockfd:套接字的文件描述符,socket()系统调用返回的fd

addr:指向存放地址信息的结构体的首地址

addrlen:存放地址信息的结构体的大小,其实也就是sizof(struct sockaddr)

编译并在ubuntu下运行

编译

gcc -o server-while-tcp.out server-while-tcp.c
gcc -o client.out client.c

运行

./server-while-tcp.out
./client.out 192.168.1.***    

修改服务器为多线程模式

server.cpp

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<pthread.h>
#include<unistd.h>
#include<arpa/inet.h>
using namespace std;
const int BUF_SIZE=100;
const int MAX_CLIENT=256;
 
int clientCnt;
int clientSocks[MAX_CLIENT];
pthread_mutex_t mutex;
 
void* handleClient(void *arg);
void sendMsg(char *msg,int len);
void errorHandling(char *msg);
 
int main()
{
	int serverSock,clientSock,port;
	sockaddr_in serverAddr,clientAddr;
	pthread_t id;
	socklen_t clientAddrSize;
 
	cout<<"Input port:";
	cin>>port;
 
	pthread_mutex_init(&mutex,NULL);
	serverSock=socket(PF_INET,SOCK_STREAM,0);
 
	memset(&serverAddr,0,sizeof(serverAddr));
	serverAddr.sin_family=AF_INET;
	serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	serverAddr.sin_port=htons(port);
 
	if(bind(serverSock,(sockaddr *)&serverAddr,sizeof(serverAddr))==-1)
		errorHandling("bind() error!");
	if(listen(serverSock,5)==-1) errorHandling("listen() error!");
 
	while(1)
	{
		clientAddrSize=sizeof(clientAddr);
		clientSock=accept(serverSock,(sockaddr *)&clientAddr,&clientAddrSize);
 
		pthread_mutex_lock(&mutex);
		clientSocks[clientCnt++]=clientSock;
		pthread_mutex_unlock(&mutex);
 
		pthread_create(&id,NULL,handleClient,static_cast<void *>(&clientSock));
		pthread_detach(id); 		//该函数的功能和pthread_join一样,但不会进入阻塞状态。
		cout<<"Connected client IP:"<<inet_ntoa(clientAddr.sin_addr)<<endl;
	}
 
	close(serverSock);
	return 0;
}
 
void errorHandling(char *msg)
{
	cerr<<msg<<endl;
	exit(1);
}
 
void* handleClient(void *arg)
{
	int clientSock(*(static_cast<int *>(arg))),len;
	char msg[BUF_SIZE];
 
	while((len=read(clientSock,msg,sizeof(msg)))!=0)
		sendMsg(msg,len);
 
	pthread_mutex_lock(&mutex); 		//删除断开连接的客户端对应的套接字
	for(int i=0;i<clientCnt;i++)
	{
		if(clientSock==clientSocks[i])
		{
			for(int j=i;j<=clientCnt-2;j++)
				clientSocks[j]=clientSocks[j+1];
			break;
		}
	}	
	clientCnt--;
	pthread_mutex_unlock(&mutex);
	close(clientSock);
	return NULL;
}
 
void sendMsg(char *msg,int len) 		//将任何一个客户端发来的消息一一发送给全部客户端
{
	pthread_mutex_lock(&mutex);
	for(int i=0;i<clientCnt;i++)
		write(clientSocks[i],msg,len);
	pthread_mutex_unlock(&mutex);
}

client.cpp

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<pthread.h>
#include<unistd.h>
#include<arpa/inet.h>
using namespace std;
const int BUF_SIZE=100;
 
char name[BUF_SIZE],buf[BUF_SIZE];
 
void* sendMsg(void *arg);
void* recvMsg(void *arg);
void errorHandling(char *msg);
 
int main()
{
	int sock,port;
	sockaddr_in serverAddr;
	pthread_t sendThread,recvThread;
	void *threadReturn;
	char ip[BUF_SIZE];
 
	cout<<"Input ip:";
	cin>>ip;
	cout<<"Input port:";
	cin>>port;
	cout<<"Input name:";
	cin>>name;
 
	sock=socket(PF_INET,SOCK_STREAM,0);
 
	memset(&serverAddr,sizeof(serverAddr),0);
	serverAddr.sin_family=AF_INET;
	serverAddr.sin_addr.s_addr=inet_addr(ip);
	serverAddr.sin_port=htons(port);
 
	if(connect(sock,(sockaddr *)&serverAddr,sizeof(serverAddr))==-1)
		errorHandling("connect() error!");
 
	pthread_create(&sendThread,NULL,sendMsg,static_cast<void *>(&sock));
	pthread_create(&recvThread,NULL,recvMsg,static_cast<void *>(&sock));
	pthread_join(sendThread,&threadReturn);
	pthread_join(recvThread,&threadReturn);
	
	close(sock);
	return 0;
}
 
void errorHandling(char *msg)
{
	cerr<<msg<<endl;
	exit(1);
}
 
void* sendMsg(void *arg)
{
	int sock(*(static_cast<int *>(arg)));
	char input[BUF_SIZE];
 
	while(1)
	{
		cin>>input;
		if(!strcmp(input,"q")||!strcmp(input,"Q"))
		{
			close(sock);
			exit(0);
		}
		strcpy(buf,name);
		strcat(buf,":");
		strcat(buf,input);
		write(sock,buf,strlen(buf));
	}
	return NULL;
}
 
void* recvMsg(void *arg)
{
	int sock(*(static_cast<int *>(arg)));
	char output[BUF_SIZE];
	
	while(1)
	{
		int len(read(sock,output,BUF_SIZE-1));
		if(len==-1) return (void *)-1;
		
		output[len]=0;
		cout<<output<<endl;
	}
	return NULL;
}

编译并在ubuntu下运行

gcc -o srv srv.c
gcc -o cli cli.c

运行

./srv
./cli 192.168.1.***     

echo sever

  • 服务端改进
  • /* 在客户端发送数据后面加上 */
    iRecvLen = iRecvLen = recv(iSocketClient, ucRecvBuf, 999, 0);
            if (iRecvLen <= 0)            
            {
                close(iSocketClient); 
                return -1;
            }
            else 
            {
                ucRecvBuf[iRecvLen] = '\0'; 
                printf("Feedback:%s\n", ucRecvBuf);
            }
    
    /* 在服务端打印数据后面加上 */
        iRecvLen = send(iSocketClient, ucRecvBuf, strlen(ucRecvBuf), 0);
        if(iRecvLen <= 0)
        {
            close(iSocketClient);
            return -1;
        }
    

    echo大写

    /* 一个完整字符串大写转换函数 */
    #include<stdio.h>
    
    int main()
    {
        char ch[100];
        int i;
        while(scanf("%c",&ch[i])!=EOF)
        {
            if(ch[i]>='a'&&ch[i]<='z')
                        ch[i]=ch[i]-32;  
                            printf("%c",ch[i]);
        }
        return 0;
    }
    
    /* 修改为我们使用的函数 */
    int charup(unsigned char ch[1000]);     //声明
    charup(ucRecvBuf);                      //调用
    int charup(unsigned char ch[1000])
    {
        int i = 0;
        while (ch[i] != '\0')
        {
            if(ch[i]>='a'&&ch[i]<='z')
            ch[i]=ch[i]-32;  
            i ++;
        }        
        return 0;
    }
    
    

    引用

http://tuoxie174.blog.51cto.com/1446064/413189 

Linux connect系统调用_Blue summer的博客-CSDN博客_connect 系统调用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值